执行非交互式的rgrep

10

我正在尝试从一个小的Emacs Lisp实用程序中运行rgrep命令,但是出现了奇怪的错误。该命令的描述如下:

rgrep是一个交互式编译的Lisp函数。

(rgrep REGEXP&optional FILES DIR CONFIRM)

在以DIR为根目录的目录树中递归地grep文件名匹配shell模式FILES中的REGEXP。搜索限制于匹配的文件名。FILES可以使用在`grep-files-aliases`中定义的缩写,例如,输入代码“ch”等效于“*。[ch] ”。

使用C-u前缀,您可以在执行之前编辑构造的Shell命令行。 使用两个C-u前缀,直接编辑并运行“grep-find-command”。

在缓冲区中收集输出。 当find异步运行时,您可以使用C-x `(M-x next-error)或grep输出缓冲区中的RET转到grep找到匹配项的行。

此命令与M-x lgrep和M-x grep-find共享参数历史记录。

我尝试执行:

(rgrep "something" "all" "~/projects/")

我得到了

 *** Eval error ***  Wrong type argument: stringp, nil

很明显,所有的参数都是字符串,所以我不明白这个空值是从哪里来的。

我正在Debian Testing系统上运行Emacs 23.3。

提前感谢您的帮助!


对我来说完全没有问题。尝试在 Emacs 中运行,不使用你的 .emacs (emacs -q)。另外,在运行之前添加(setq debug-on-error t)以获取回溯信息,这将提供更多信息。 - Trey Jackson
你可能在运行那段代码之前交互式地运行了rgrep,并且grep-find-template的值不为nil。 - Bozhidar Batsov
4个回答

5
我认为这是因为您没有定义“grep-find-template”。根据我的调试结果,这肯定是该命令在我的版本上产生错误的原因。请查看该变量的帮助文档。
祝好。
附注:这在交互式和非交互式调用之间有所区别。
"find . <X> -type f <F> -print0 | \"xargs\" -0 -e grep <C> -nH -e <R>"

当以交互方式调用时,“grep-calc-defaults”会设置该值。

另外,我认为您只需小心您的调用。如果没有找到匹配项,您将收到“Grep exited abnormally with code 123”错误。

mkdir -p ~/a/b
cp ~/.bash* ~/a/b
emacs -q

C-x b <RET> *scratch*
(grep-compute-defaults)
(rgrep "^.*\\?\=.*$" "*bash*" "~/a")

......有很多匹配项!


是的,你说得对。不过我有一个疑问 - 如果我在运行rgrep之前直接调用calc-defaults,那么find会出现一些异常退出错误。在那个时候,grep-find-template的值似乎看起来很好。你有什么想法是什么原因导致这种情况吗? - Bozhidar Batsov
Bozhidar Batsov:您使用的“all”别名可能也是一个问题。这似乎在交互调用中处理。您可能希望将其更改为相关的正则表达式“.*”。 - phils

4
当您以编程方式调用rgrep时,会出现此问题的原因是所有变体的grep的所有交互式调用都在交互式调用中调用了grep-compute-defaults。但是,当您以编程方式调用时,这不会被评估。
最简单的解决方法是添加:
(eval-after-load "grep"
  '(grep-compute-defaults))

在您的代码中,可以使用这种方式来强制调用它(但仅在需要时调用)。


是的,我已经弄清楚了。我的真正问题是在调用rgrep之前调用grep-compute-defaults会引入一些其他问题 - 现在我从rgrep执行的find命令中得到异常退出错误。也许除了调用grep-computre-defaults之外还需要做更多的事情? - Bozhidar Batsov

2
以下对我来说看起来工作得很好:
(defadvice rgrep (around rgrep-init)
  "Init grep defaults before calling rgrep non-interactively."
  (when (not (called-interactively-p))
    (grep-compute-defaults))
  ad-do-it)

(ad-activate 'rgrep)

(rgrep "something" "all" "~/projects/")

2
根据 Emacs 手册:
M-x lgrep (本地 grep) 和 M-x rgrep (递归 grep) 命令是 grep 和 grep-find 更加用户友好的版本,会分别提示输入要匹配的正则表达式、要搜索的文件和搜索的基目录。
对于当前的问题,我们不需要这种妨碍操作的“用户友好性”。我们可以使用 plain "grep" elisp 函数,它更适合非交互式使用。基本上,此函数将作为参数接受您必须使用的任何 grep 命令行以实现所需结果。最大的灵活性!
以下是您情景下所需内容的示例:
(grep "grep --color -rn something ~/projects/")

这是grep选项的另一个更复杂的用法,用于匹配Python文件中的完整单词:

(grep "grep --include=\"*.py\" --color -rnw your_pattern files_root_dir")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接