使用Emacs在未打开的文本文件中进行递归查找和替换

229
作为对这个问题的追踪,它试图找出如何做一些看似容易的事情,尤其是阻止我更多地习惯于使用Emacs,而是启动我已经熟悉的编辑器。我经常在编辑多个文件时使用这里的示例。
在Ultraedit中,我会按Alt+s然后按p,显示一个带有以下选项的对话框:查找(包括在多行中使用正则表达式),替换为,在文件/类型中,目录,匹配大小写,仅匹配整个单词,列出已更改的文件和搜索子目录。通常情况下,我会首先使用鼠标点击并拖动选择要替换的文本。
只使用Emacs本身(在Windows XP上),而不调用任何外部实用程序,如何将所有foo\nbar替换为bar\nbaz在某个文件夹及其所有子文件夹中的*.c*.h文件中。也许Emacs不是最好的工具来完成这个任务,但如何以最少的命令轻松地完成它呢?
15个回答

2
  1. M-x project-query-replace-regexp RET(确保您的文件已保存!)。

  2. M-x rgrep RET 然后在每个缓冲区内使用 query-replace。这种方法很好,因为您可以跟踪所有出现的情况,并且可以将搜索限制为某些扩展名。


很遗憾,project-query-replace-regexp 不是很可靠。 - young_souvlaki

2
另一种选择是使用Icicles搜索。这是一种不同类型的增量搜索,它使用小型缓冲区输入的完成对搜索结果进行匹配。随着您修改当前输入,匹配的结果集将在缓冲区*Completions*中更新。
您可以搜索任意数量的文件、缓冲区或书签位置,可以使用小型缓冲区模式(例如regexp)匹配来选择这些位置。
当您访问搜索结果时,您可以根据需要替换整个结果或仅替换与当前小型缓冲区输入匹配的部分。按需替换意味着您不会被依次询问每个搜索结果;您可以直接访问所需的结果,以任何顺序。如果您要进行有限数量的替换,则此方法可能比查询替换更有效:您可以跳过详尽的y/n提示。
搜索是基于您定义的搜索上下文进行的-- 您不限于搜索目标文件中的所有文本(例如,您可以跳过注释或特定类型的程序部分)。搜索上下文的简单示例是一行,就像grep一样,但上下文可以是任何您喜欢的匹配模式的文本块。通常,您使用regexp定义搜索上下文,但也可以使用函数。除了定义自己的上下文之外,还有预定义的Icicles搜索命令,用于不同类型的上下文:文本属性或覆盖属性块、thing-at-point things等。
您还可以按各种排序顺序对搜索结果进行排序,以便更轻松地访问/导航。

1

我想再推荐一个很棒的工具,它还没有被提到过,那就是Helm

它是许多标准Emacs操作的很好替代品,包括完成、搜索等。特别是helm-find-files允许在多个选定文件中执行查询替换(包括正则表达式)。

只需打开helm-find-files,用M-SPC标记相关文件,然后使用F6F7在选定的文件中运行查询替换或查询替换正则表达式。


helm-find-files 可以使用正则表达式标记,而不是 M-SPC 吗? - Nordlöw

1
令人惊讶的是,至今还没有给出使用已经为这种情况创建的-batch Emacs模式的答案。所以这里有一个简单的例子:
$ echo foo > 1 && echo foo > 2 && echo foo > 3
$ emacs -batch --eval '(progn (dolist (file command-line-args-left) (find-file file) (replace-regexp "foo" "bar") (save-buffer) (kill-buffer)))' ./1 ./2 ./3
Mark set
Replaced 1 occurrence
Mark set
Replaced 1 occurrence
Mark set
Replaced 1 occurrence
$ grep "" ./1 ./2 ./3
./1:bar
./2:bar
./3:bar

值得单独注意的是,如果您的替换内容不适合一行,您也可以将其保存到文件中,如下所示:
$ cat my_replace.el
(dolist (file command-line-args-left)
  (find-file file)
  (replace-regexp "foo" "bar")
  (save-buffer)
  (kill-buffer))
$ emacs -batch -l my_replace.el ./1 ./2 ./3
Mark set
Replaced 1 occurrence
Mark set
Replaced 1 occurrence
Mark set
Replaced 1 occurrence

-2

虽然不是Emacs,但xxdiff带有一个名为xx-rename的工具,可以同时为多个字符串进行重命名(例如:From To from to FROM TO),并提供交互提示、保存所有修改文件的备份,并生成带有上下文的更改日志。这是我在进行大规模/全局重命名时经常使用的工具。


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