作为这个问题的后续,它试图找出如何做这样的事情,这应该很容易,这尤其阻止我更习惯于使用Emacs,而是启动我已经熟悉的编辑器。在编辑多个文件时,我经常使用这个示例。

在Ultraedit中,我用Alt+s然后p来显示一个带有选项的对话框:查找(包括跨多行使用正则表达式),替换,在文件/类型中,目录,匹配大小写,仅匹配整个单词,列出更改的文件和搜索子目录。通常我会先用鼠标点击-拖动选择我想要替换的文本。

只使用Emacs本身(在Windows XP上),不调用任何外部实用程序,如何替换所有的foo\nbar与bar\nbaz在*.c和*.h文件中的一些文件夹和它下面的所有文件夹。也许Emacs并不是最好的工具,但是如何用最少的命令就能轻松完成呢?


当前回答

我通常使用其他工具来执行这项任务,EmacsWiki的跨文件查找和替换条目中提到的许多方法似乎都很有用,但Findr包看起来很有前途。

窃取部分源文件:

(defun findr-query-replace (from to name dir)
  "Do `query-replace-regexp' of FROM with TO, on each file found by findr.

其他回答

它不是Emacs,但xxdiff附带了一个名为xx-rename的工具,该工具可以一次对多个字符串执行此操作(例如From To From To From To From To),并带有交互式提示,保存所有修改文件的备份,并生成一个简短的上下文更改日志。这是我在进行大型/全局重命名时倾向于使用的方法。

对于这个任务,使用dred来递归到一个深目录树将会有点慢。您可以考虑使用标记-查询-替换。这确实意味着要花费一些钱来创建一个标签表,但这通常是有用的,而且是快速的。

M-x find-name-dired RET it may take some time for all the files to appear in the list, scroll to bottom (M->) until "find finished" appears to make sure they all have loaded Press t to "toggle mark" for all files found Press Q for "Query-Replace in Files...": you will be prompted for query/substitution regexps. Proceed as with query-replace-regexp: SPACE or y to replace and move to next match, n to skip a match, etc. Type ! to replace all occurrences in current file without asking, N to skip all possible replacement for rest of the current file. (N is emacs 23+ only) To do the replacement on all files without further asking, type Y. Call “ibuffer” (C-x C-b if bound to ibuffer, or M-x ibuffer RET) to list all opened files. Type * u to mark all unsaved files, type S to save all marked files * * RET to unmark all marks, or type D to close all marked files

这个答案结合了这个答案、这个网站和我自己的笔记。使用Emacs 23+。

另一个选择是使用Icicles搜索。这是一种不同类型的增量搜索,它使用对搜索命中的迷你缓冲区输入的完成。当您修改当前输入时,匹配命中的集合将在缓冲区*Completions*中更新。

您可以搜索任意数量的文件、缓冲区或书签位置,您可以使用迷你缓冲区模式(例如regexp)匹配进行选择。

当您访问一个搜索结果时,您可以根据需要替换整个搜索结果或匹配当前小缓冲区输入的部分。按需替换意味着您不会依次查询每个搜索命中;你可以按任意顺序直接访问你想要的点击率。如果要进行的替换数量有限,这种方法可能比查询-替换更有效:跳过详尽的y/n提示。

Search is over search contexts that you define -- you are not limited to searching all of the text in the target files (e.g., you can skip comments or particular kinds of program sections). A simple example of a search context is a line, as in grep, but a context can be any pattern-matched block of text you like. Typically you define the search contexts using a regexp, but you can instead use a function. In addition to defining your own, there are predefined Icicles search commands for different kinds of contexts: blocks of text properties or overlay properties, thing-at-point things, etc.

您还可以以各种排序顺序对搜索命中进行排序,以便于访问/导航。

对于打开的缓冲区,这是我所做的:

(defun px-query-replace-in-open-buffers (arg1 arg2)
  "query-replace in all open files"
  (interactive "sRegexp:\nsReplace with:")
  (mapcar
   (lambda (x)
     (find-file x)
     (save-excursion
       (goto-char (point-min))
       (query-replace-regexp arg1 arg2)))
   (delq
    nil
    (mapcar
     (lambda (x)
       (buffer-file-name x))
     (buffer-list)))))