例如:在VIM中,
test
sample replace
test1
replace
sample test2
:g / sample / s / replace / test3 / - 只会在匹配的“sample”行中替换“replace”
test
sample test3
test1
replace
sample test2
在VIM中,只能在非匹配线上进行替换 :v / sample / s / replace / test3 - 仅在不包含“sample”的非匹配行上替换“replace”
test
sample replace
test1
test3
sample test2
如何使用emacs完成上述事情?
答案 0 :(得分:17)
您使用的是Emacs 24吗?如果是这样,您可以使用内置的发生编辑模式:
occur
RET (模式) RET 有些第三方库可以在早期版本的Emacs上执行类似的技巧。我相信moccur-edit
就是其中之一,但我从未使用它。
编辑:关于问题的第二部分,虽然我不熟悉更直接的实现方法,但我们可以通过这种方法来实现它:
occur
RET .
RET 获取包含 all 的缓冲区线flush-lines
RET (pattern) RET 删除匹配行答案 1 :(得分:1)
我认为没有内置任何内容,但有些elisp可以做到:
(defun my-replace-on-matching-lines (&optional arg)
"Replace text on lines that match a regexp.
With prefix arg, replace on non-matching lines."
(interactive "P")
(let* ((regexp (concat ".*"
(read-from-minibuffer
(concat "Replace on lines "
(if arg "not " "")
"matching regexp: "))))
(replace (read-from-minibuffer "Replace: "))
(with (read-from-minibuffer (concat "Replace " replace " with: ")))
match)
(save-excursion
(goto-char (point-min))
(while (not (eobp))
(setq match (looking-at regexp))
(when (if arg (not match) match)
(while (search-forward replace (point-at-eol) t)
(replace-match with nil t)))
(forward-line)))))
答案 2 :(得分:1)
Icicles 搜索背后的主要思想是首先定义搜索 上下文 ,然后在这些上下文中搜索子串和正则表达式等模式。您可以轻松地搜索non-contexts(上下文之外的文本)作为上下文,从而解决您的第二个问题。
在这种情况下,搜索上下文是包含sample
的行。此正则表达式定义了上下文:.*sample.*
,因为.
匹配除换行符之外的任何字符。
对于此搜索,您不希望替换整个搜索上下文,因此您应将选项icicle-search-replace-whole-candidate-flag
设置为nil。默认情况下它是非零的 - 您只需要按 M -_ (一次)来切换它。这使得当前迷你缓冲区输入与被替换的文本匹配,而不是使整个上下文成为替换文本。
您可以按任意顺序访问所需的任何上下文(包含sample
)的任何内容。如果你愿意,你可以在其中一些或全部循环。您甚至可以通过各种方式对上下文进行排序,以便于比较或更改循环顺序。 (排序不会以任何方式更改文本 - 上下文按缓冲区*Completions*
排序。)
但是在这里你真的对那些包含replace
的上下文感兴趣,所以你在迷你缓冲区中输入replace
。只有这些背景仍然是候选人。如果您更改了迷你缓冲区输入,则搜索命中集 - 匹配的上下文 - 会动态更改。同样,您可以按任何顺序访问任何匹配的上下文,在它们之间循环等等。
以下是步骤:
.*sample.*
,然后按 RET 。*Completions*
中。搜索上下文是完成候选。replace
以将上下文缩小为包含replace
的内容。replace
)匹配的上下文部分。test3
。replace
的第一次出现。你再次点击 S-RET 替换下一个,然后再替换下一个,等等。请注意,这可让您在同一个上下文中逐个替换多次出现的replace
。
如果您知道要替换{em>所有出现的replace
,请在步骤9中点击 M- | 来执行此操作。
替换只是按需。你基本上只是在寻找。您可以决定访问哪些搜索。在我给出的示例中,您使用C-down
在搜索匹配中循环,但您可以轻松访问某些匹配。
当您访问搜索时,您决定是否在那里进行替换。您不会依次查询每次点击并被迫回复y
或n
等,如query-replace
中所示。
(如果过滤后只有一个搜索上下文,例如,只有一行同时包含sample
和replace
,那么您将立即转到该上下文,而不是有机会替换部分内容。)
要搜索非 -contexts而不是上下文---即包含sample
的行之外的文本,请点击 CM-~ 在搜索完成期间,在内部/外部环境中切换搜索。 (切换从下一次搜索开始生效,而不是你点击 C-M-〜的那个。)
(对于包含grep
的行,另一种方法是sample
,但存在一些差异,
然后点击*grep*
缓冲区中的 C -` ,然后按上述步骤进行操作--- IOW,使用grep
定义搜索上下文。)
答案 3 :(得分:0)
您可以使用regluar表达式搜索/替换:
M-x query-replace-regexp (or C-M-%)
\(sample.*\)replace RET
\1test3
这会在replace
之前test3
的所有行上替换sample
的{{1}}。
这并不是您所要求的(replace
可以在线上的任何位置)。
答案 4 :(得分:0)
replace-regexp
(或query-replace-regexp
)replace\(.*sample.*\)\|\(sample.*?\)replace\(.*\)
\2test3\1\3
这种方法只处理问题的第一部分。第二部分可能需要编写一些Lisp代码,因为Emacs regexp不包含先行断言。
答案 5 :(得分:-1)
到目前为止,这个问题最明显的答案是不存在的......
如果您使用evil-mode
,则可以在Emacs中使用相同的:g
(:global
)和:v
(:vglobal
)ex命令。
:g/sample/s/replace/test3
:v/sample/s/replace/test3
警告: 不以斜杠结束命令,否则会破坏这些命令的行为。斜杠后跟一个或多个标志就可以了。