vim -- 查找和替换
%s/foo/bar/g
在所有行中寻找‘foo’,并且用‘bar’替换
:s/foo/bar/g
在当前行寻找‘foo’,并且用‘foo’替换
:%s/foo/bar/gc
将每一个‘foo',并用’bar‘替换,但是替换时询问
%s/\<foo\>/bar/gc
查找单词完全匹配’foo‘替换成bar,但是替换时询问
:%s/foo/bar/gci
查找’foo‘并且替换成’bar‘但是大小写不敏感,替换时询问,
:%s/foo\c/bar/gc是与上一个相同,因为\c是大小写不敏感的
使用:set noingorecase查找时就是大小写敏感的
:%s/foo/bar/gcI
将每一个’foo‘替换成’bar‘,大小写敏感,替换时询问
:$s/foo\C/bar/gcI与上一条相同
使用:set ignorecase查找时不是大小写敏感的
g表示global(全局的) - 每一行出现的都被改变,不仅是每一行的第一个
这样做的假设是默认’gdefault‘ 和 ’edcompatible‘ 是关的,所以需要:%s///g使用全局替换
使用:set gdefault时,:%s///是使用全局替换,而:%s///g不是
使用g选项主要是相反的意思
使用c选项时,对每个替换操作需要确认。Vim可能会输出replace with foobar (y/n/a/q/l/^E/^Y)?, 这里foobar是:%s/.../...,你可以使用y进行替换,n跳过这个替换,a对当前及以后所有进行替换操作(a是 all remaining matches),q是退出这个操作,l是对当前进行替换操作,然后退出操作,(l是last),^E是指按下Ctrl + E滚到上一屏,^Y是指Ctrl + Y滚到下一屏,然而最后两个选项是可选的。
还在使用c标志,Vim会跳到它从顶部查找到的第一个匹配项,提示你确认对匹配执行替换。Vim IncSearch突出匹配的文本给你一个视觉提示在对哪个匹配进行操作。
查找范围
:s/foo/bar 将当前行’foo‘全部替换为‘bar’
:%s/foo/bar/g 将所有行的’foo‘全部替换为’bar‘
:5,12s/foo/bar/g 将5-12行(包括5行和12行)中的’foo'全部替换为‘bar’
:'a,'bs/foo/bar/g 从标记a到标记b所有行中的‘foo’替换为‘bar’
:'<,'>s/foo/bar/g 当使用 +visual时,在visual选中的区域。Vim会自动加入 ( '<, '>)当你选中一片区域,并且按下:时。
:.,$s/foo/bar/g 从当前行(.)到最后一行($)将’foo‘替换成’bar‘
:.,+2s/foo/bar/g 从当前行(.)到下两行将’foo‘替换成’bar‘
:g/^baz/s/foo/bar/g 以’baz‘开头的所有行中的’foo‘替换成’bar'
注意:As of Vim 7.3, substitutions applied to a range defined by marks or a visual selection (which uses a special type of marks '< and '>) are not bounded by the column position of the marks by default. Instead, Vim applies the substitution to the entire line on which each mark appears unless the \%V
atom is used in the pattern like: :'<,'>s/\%Vfoo/bar/g
.
使用查找时:
.
, *
, \
, [
, ^
, 和 $ 是元字符
+
, ?
, |
, &
, {
, (
, and )
must be escaped to use their special function.
\/
是 /(用反斜杠 + 斜杠查找斜杠)
\t 是tab,\s是空格
\n 是新的一行,\r是CR(回车符 = Ctrl + M = ^M)
[]在中括号之间的内容表示要查找内容的一个集合,字符的范围可以用一个 - , 比如,要查找一个字符a,b,c, 或者是数字1,可以使用[1a-c]表示,^表示取反,例如[^1a-c]表示匹配除1,a,b,c以外的所有字符
\{#\}用来匹配剩下的字符,/foo.\{2\} 会匹配foo和紧跟着的两个字符,\没有必要,/foo.{2}会有相同的结果
\(foo\) 对‘foo’制造了一个回溯引用,括号没有\表示匹配,所以\在这里是必须的
使用替换时:
\r表示新的一行,\n表示没有字符
\&表示&
\0
inserts the text matched by the entire pattern
\1插入第一个回溯引用,\2表示插入第二个回溯引用
也可以使用其他的分割符来进行查找,例如
:s#http://www.example.com/index.html#http://example.com/#
使用\zs和\ze来指定替换的开始和结束,比如
:s/Copyright 2007 All Rights Reserved/Copyright 2008 All Rights Reserved/
可以用
:s/Copyright \zs2007\ze All Rights Reserved/2008/
使用当前的word或是寄存器
:%s//bar/g
用‘bar’替换上一个匹配的模式
:%s/foo/<c-r><c-w>/g
- Replace each occurrence of 'foo' with the word under the cursor.
<c-r><c-w>
means that you press Ctrl-R then Ctrl-W.- The word under the cursor will be inserted as though you typed it.
:%s/foo/<c-r><c-a>/g
- Replace each occurrence of 'foo' with the WORD under the cursor (delimited by whitespace).
<c-r><c-a>
means that you press Ctrl-R then Ctrl-A.- The WORD under the cursor will be inserted as though you typed it.
:%s/foo/<c-r>a/g
- Replace each occurrence of 'foo' with the contents of register 'a'.
<c-r>a
means that you press Ctrl-R thena
.- The contents of register 'a' will be inserted as though you typed it.
:%s/foo/<c-r>0/g
- Same as above, using register 0 which contains the text from the most recent yank command. Examples of yank (copy) commands are
yi(
which copies the text inside parentheses around the cursor, andy$
which copies the text from the cursor to the end of the line. After a yank command which did not specify a destination register, the copied text can be entered by pressing Ctrl-R then0
.
:%s/foo/\=@a/g
- Replace each occurrence of 'foo' with the contents of register 'a'.
\=@a
is a reference to register 'a'.- The contents of register 'a' is not shown in the command. This is useful if the register contains many lines of text.
:%s//<c-r>//g
- Replace each match of the last search pattern with the
/
register (the last search pattern). - After pressing Ctrl-R then
/
to insert the last search pattern (and before pressing Enter to perform the command), you could edit the text to make any required change.
:%s/<c-r>*/bar/g
- Replace all occurrences of the text in the system clipboard (in the
*
register) with 'bar' (see next example if multiline). - On some systems, selecting text (in Vim or another application) is all that is required to place that text in the
*
register.
:%s/<c-r>a/bar/g
- Replace all occurrences of the text in register 'a' with 'bar'.
<c-r>a
means that you press Ctrl-R thena
. The contents of register 'a' will be inserted as though you typed it.- Any newlines in register 'a' are inserted as
^M
and are not found. - The search works if each
^M
is manually replaced with '\n' (two characters: backslash, 'n'). - This replacement can be performed while you type the command:
:%s/<c-r>=substitute(@a,"\n",'\\n','g')<CR>/bar/g
- The
"\n"
(double quotes) represents the single character newline; the'\\n'
(single quotes) represents two backslashes followed by 'n
'. - The
substitute()
function is evaluated by the<c-r>=
(Ctrl-R=
) expression register; it replaces each newline with a single backslash followed by 'n
'. - The
<CR>
indicates that you press Enter to finish the=
expression.
:%s/<c-r>0/bar/g
- Same as above, using register 0 which contains the text from the most recent yank command
使用例子:
:%s/foo/bar/
将每一行第一次出现的‘foo’用‘bar’替换
:%s/.*\zsfoo/bar/
将每一行最后一次出现的'foo'用‘bar’替换
:%s/\<foo\>//g
对每一行,删除所有出现的‘foo’
:%s/\<foo\>.*//
将每一行出现的‘foo’以及这一行之后的所有文本删除
:%s/\<foo\>.\{5}//
将每一行出现的‘foo’以及之后的5个字符删除
:%s/\<foo\>\zs.*//
将每一行出现在‘foo’之后的文本删除
:%s/.*\<foo\>//
将每一行中的‘foo’和它之前的文本删除
:%s/.*\ze\<foo\>//
将每一行出现在‘foo’之前的文本删除
:%s/.*\(\<foo\>\).*/\1/
将每一行‘foo'之前的文本和之后的文本删除
:s/^\(\w\)/\u\1/
将当前行的第一个字符改成大写
:%s/\(.*\n\)\{5\}/&\r/
每5行插入一个空白行
将\(.*\n\)(任意一行)重复5次(\{5\})
替换成&(匹配到的文本,就是5行内容),后面加上新的一行(\r)
:%s/\<foo\(\a*\)\>/\=len(add(list, submatch(1)))?submatch(0):submatch(0)/g
得到一个匹配结果的列表,列表必须存在
设置modified标志,因为替换,但是内容没有改变
:%s/\<foo\(\a*\)\>/\=add(list, submatch(1))/gn
This has the advantage, that the buffer won't be marked modified and no extra undo state is created. The expression in the replacement part is executed in the sandbox and not allowed to modify the buffer.