以非交互方式执行 rgrep
Posted
技术标签:
【中文标题】以非交互方式执行 rgrep【英文标题】:Executing rgrep non-interactively 【发布时间】:2011-08-10 16:35:54 【问题描述】:我正在尝试从一个小型 Emacs Lisp 实用程序运行 rgrep 命令,但遇到了一个奇怪的错误。命令说明为:
rgrep 是一个交互式编译的 Lisp 函数。
(rgrep REGEXP &optional FILES DIR CONFIRM)
在以 DIR 为根的目录树中的 FILES 中递归 grep 查找 REGEXP。 搜索仅限于匹配 shell 模式 FILES 的文件名。 FILES 可以使用
grep-files-aliases', e.g. entering
ch' 中定义的缩写,相当于`*.[ch]'。使用 C-u 前缀,可以编辑构造的 shell 命令行 在执行之前。带两个C-u前缀,直接编辑运行 `grep-find-command'。
在缓冲区中收集输出。虽然 find 异步运行,但您可以 在 grep 输出缓冲区中使用 C-x ` (M-x next-error) 或 RET 转到 grep 找到匹配的行。
此命令与 M-x lgrep 和 M-x 共享参数历史记录 grep 查找。
我试着跑:
(rgrep "something" "all" "~/projects/")
我得到了
*** Eval error *** Wrong type argument: stringp, nil
显然所有的参数都是字符串,所以我不明白这个 nil 是从哪里来的。
我在 Debian 测试上运行 Emacs 23.3。
提前感谢您的帮助!
【问题讨论】:
对我来说很好用。尝试在没有 .emacs (emacs -q
) 的情况下在 Emacs 中运行。此外,在运行它之前,添加(setq debug-on-error t)
以获取回溯,这将提供更多信息。
您可能在运行该代码之前已经交互式地运行了 rgrep,并且您对 grep-find-template 的值不是 nil。
【参考方案1】:
我认为这是因为您没有定义“grep-find-template”。这当然是(已调试)该命令在我的版本上产生错误的原因。查看该变量的帮助。
干杯。
ps。这就是交互调用与否的区别..
"find . <X> -type f <F> -print0 | \"xargs\" -0 -e grep <C> -nH -e <R>"
..在交互调用时由 'grep-calc-defaults' 设置
pps。我认为你只需要小心你的电话。如果未找到匹配项,您将收到“Grep 异常退出,代码 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:您对"all"
别名的使用也可能是个问题。这看起来也可以在interactive
调用中处理。您可能希望将其更改为关联的正则表达式 ".*"
。【参考方案2】:
当您以编程方式调用rgrep
时得到此信息的原因是,所有对grep
变体的interactive
调用都在interactive
调用中调用了grep-compute-defaults
。当您以编程方式调用时,这不会得到评估。
解决此问题的最简单方法是添加
(eval-after-load "grep"
'(grep-compute-defaults))
在您的代码中,这将强制调用它(但仅在需要时)。
【讨论】:
是的,我已经想通了。我真正的问题是在 rgrep 引入其他问题之前调用 grep-compute-defaults - 现在我从 rgrep 执行的 find 命令中得到一个异常退出错误。除了调用 grep-compute-defaults 之外,也许还有其他事情需要做?【参考方案3】:以下对我来说似乎工作正常:
(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/")
【讨论】:
【参考方案4】:根据 Emacs 手册:
命令 M-x lgrep (local grep) 和 M-x rgrep (recursive grep) 是 grep 和 grep-find 更用户友好的版本,它们分别提示要匹配的正则表达式、要搜索的文件和基本目录用于搜索。
对于手头的问题,我们不需要这种妨碍用户使用的“用户友好性”。我们可以使用更适合非交互使用的普通“grep”elisp 函数。基本上,此函数将您必须使用的任何 grep 命令行作为参数来实现所需的结果。最大的灵活性!
这是您的场景的样子:
(grep "grep --color -rn something ~/projects/")
这里是 grep 选项的另一个更复杂的用法,仅匹配 Python 文件中的完整单词:
(grep "grep --include=\"*.py\" --color -rnw your_pattern files_root_dir")
【讨论】:
以上是关于以非交互方式执行 rgrep的主要内容,如果未能解决你的问题,请参考以下文章