以非交互方式执行 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. enteringch' 中定义的缩写,相当于`*.[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的主要内容,如果未能解决你的问题,请参考以下文章

如何以非交互方式为“psql”指定密码?

使用 git 以非交互方式编辑旧提交

有没有办法以非交互方式压缩大量提交?

如何以非交互方式在 Git 中重新排序提交

仅当函数的返回值等于“Value”时,gdb 是不是可以在函数上以非交互方式有条件地中断?

仅在以非交互方式运行 bash 脚本时出现错误“cat: write error: Broken pipe”