第五部分 模式
第 12 章 按模式匹配及按原义匹配
-
调整查找模式的大小写敏感性
① 全局调整
-
ignorecase
选项打开后,Vim的查找模式将不区分大小写- 副作用:影响Vim关键字自动补全的行为。
-
smartcase
选项打开后,只要输入一个大写字母,查找方式就会变成区分大小写的,换言之,全是小写字母的模式表示忽略大小写 -
ignorecase
和smartcase
同时启用时,smartcase
占主动,即Foo
会匹配不了foo
② 局部强制调整
- 每次查找时,可以通过在任意位置加入
\c
元字符表示忽略大小写,\C
元字符表示区分大小写 - 会覆盖全局调整
-
-
原义搜索 & 正则查找
body { color: #3c3c3c; } a { color: #0000EE; } strong { color: #000; }
- 示例:要搜索上面代码中的颜色代码
magic
搜索模式:/#\([0-9a-fA-F]\{6}\|[0-9a-fA-F]\{3}\)
- 方括号缺省具有特殊含义,因此不用转义。
- 圆括号会按原义匹配字符
(
及)
,因此需要转义,且无论开闭括号都必须转义,使其具有特殊含义。 - 花括号也一样需要转义,不过,我们只需为开括号转义,而与之对应的闭括号则不用,因为Vim会推测我们的意图。
very magic
搜索模式:/\v#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})
- 使用
\v
模式开关将会激活very magic
搜索模式,即假定除_
、字母
以及数字
外的所有字符都具有特殊含义,所以各种括号不用再转义 - 用十六进制字符类进一步优化:
/\v#(\x{6}|\x{3})
,其中\x = [0-9a-fA-F]
#
是个特例啊,他虽然不属于[_a-zA-Z0-9]
,但是它不具有特殊含义,因此时按照原义进行匹配的
- 使用
②
nomagic
搜索模式nomagic
模式下和magic
模式基本一致,只是符号^
与$
代表开头和结尾- 我们可以通过
\m
与\M
开关,来分别使能magic
和nomagic
这两种语法
③
very nomagic
搜索模式- 即原义搜索,使用
\V
开启,开启后其后的模式只有反斜杠有特殊的意义,其他的都会按照原义匹配,最为直观
③ 四种模式之间的关系
- Vim 缺省使用
magic
搜索模式,magic模式的设计初衷,是想能更容易地构造简单的正则表达式,它会自动为某些额外的符号赋予特殊含义,例如:.
(匹配任意一个字符)、*
(前面的字符可以出现0到多次)以及[]
。但它却没能为诸如+
、?
、()
以及{}
等符号赋予特殊含义,这些符号还必须经过转义才具有特殊含义。 very magic
搜索模式弥补了magic
搜索模式的不足,除了[_a-zA-Z0-9]
外,它为所有符号都赋予了特殊含义。这样一来,既好记又恰好与Perl
正则表达式的规则保持一致,因此可以认为这是个正则表达式模式nomagic
模式用于模拟 vi 的行为,只是为^
和$
赋予了开头和结尾的特殊含义very nomagic
模式是最直观的方式,除了\
其他符号都没有特殊含义,都直接匹配原文- 作为通用法则,vim默认是需要打很多转义符号的 magic 模式;如果想按正则表达式查找,就用模式开关
\v
—— very magic 搜索模式;而如果你想按原义查找文本,就使用very nomagic模式;需要用到开头和结尾匹配的时候就用\M
—— nomagic搜索模式,只不过此模式下还是需要特别多的转义
- 示例:要搜索上面代码中的颜色代码
-
圆括号
① 使用圆括号捕获子匹配
\w
匹配单词类字符,包括字母、数字及下划线\W
匹配单词类字符以外的其他字符
\_s
匹配空白符或换行符
② 圆括号的分组功能
-
/\v(And|D)rew
可以匹配Andrew和Drew -
/\v%(And|D)rew
每个括号前面的%
指示Vim不要将该括号内的内容赋给寄存器\1
③ 搭配使用
/\v(%(And|D)rew) (Neil)
- 前面没有
%
的括号表示要捕获其子匹配 %(And|D)
则表示单纯使用分组功能- 这一匹配搭配
:s//\2,\1/g
使用可以把文档中的Andrew/Drew Neil
替换成Neil,Andrew/Drew
-
界定匹配的边界
-
模式是指查找域输入的正则表达式(或则按原义匹配的文本)
匹配是指在文档中被高亮显示的文本(假设
hlsearch
选项开启) -
\zs
和\ze
是用在模式里的零宽度元字符,用来界定最终匹配的始末。\zs
标志着一个匹配的起始,\ze
标志着匹配的结束例如
/Pratical\zsVim
只会高亮显示在Pratical
之后的Vim
,和/Vim
还是有明显的区别的再如
/\v"\zs[^"]+\ze"<CR>
会匹配所有在双引号之内的内容而不包含双引号,[^"]+
表示匹配1到多个非引号的字符 -
环视表达式
- Vim的元字符
\zs
与\ze
类似于Perl
的肯定型逆序环视断言和肯定型顺序环视断言 - Vim提供完整的否定型/肯定型顺序环视/逆序环视断言,但语法与Perl的语法有所区别。详见
:h perl-patterns
- 用正向环视元字符代替
\zs
和ze
:/\v"@<=[^"]+"@=
- Vim的元字符
-
-
转义问题字符
- 需要转义查找域结束符
- 正向查找
/
时,/
会被当做结束符;反向查找?
时,?
会被当做结束符 - 如果在查找域结束符之后附加某些标志位,可以调整Vim查找命令的行为。例如,如果我们运行命令
/vim/e<CR>
,光标将会移到每个匹配的结尾,而非起始
- 正向查找
- 无论哪种查找,反斜杠
\
都需要转义 - 用编程的方式转义字符
- 需要转义查找域结束符
第 13 章 查找
-
普通模式下,按下
/
键会调出 Vim 的查找提示符,可在它的后面输入要查找的模式或者原义文本- 按下
<CR>
键时,Vim才会执行查找命令,而如果换用<Esc>
键的话,查找提示符会消失,我们将重回普通模式。
- 按下
-
/
表示正向查找,?
表示反向查找 -
查找命令抵达文档结尾处时会回绕至文档开头继续查找
-
浏览查找历史与浏览命令行历史的接口完全一致,即可以使用<Up><Down>,也可以使用<C-p><C-n>,后者没有过滤功能
-
查找高亮
-
<C-r><C-w>
自动补全功能,会用当前预览的匹配结果对查找域进行自动补全。例如输入carr
,预览为carrot
,按下这两个键就会把carrot
全部填充到模式里,不用自己手动输全 -
统计当前模式的匹配个数
-
Vim 的查找偏移功能(
:h search-offset
)- 执行查找命令时,光标总会被定位于匹配的首字母上,查找偏移可以改变光标定位的位置
- 一般都是挪到匹配的最后一位,命令为
/{pattern}/e
- 如果搜索到了中途想要使用查找偏移功能,也可以利用
//e
进行补救 - 使用场景
aim to learn a new programming lang each year. Which lang did you pick up last year? Which langs would you like to learn?
将所有的lang补全为language,就可以用
/lang/e
,然后按a
输入余下部分,之后按n.
用.
范式进行处理即可 -
对完整的查找匹配进行操作
class XhtmlDocument < XmlDocument; end class XhtmlTag < XmlTag; end
- 如果要把其中的Xhtml和Xml都变成大写,可以通过以下几步
/\vX(ht)?ml\C<CR>
查找gU//e<CR>
利用上次的查找和查找偏移进行大写转换,但只能转换第一个//<CR>
重复上次的查找- 不用
n
是因为上次的查找为//e
,按n
会跳到尾部而不是头部
- 不用
- 用
.
重复gU//e<CR>
操作 - 之后就用
//<CR>.
连续操作
⭐️
textobj-lastpat
插件增加了一个i/
文本对象用于操作查找匹配,因此只需要使用gUi/
就可以完成一次修改,之后n.
即可 -
迭代完成复杂的模式
-
查找当前选中的文本 —— 即其他文本编辑器中<C-f>的功能
xnoremap * :<C-u>call <SID>VSetSearch()<CR>/<C-R>=@/<CR><CR>
xnoremap # :<C-u>call <SID>VSetSearch()<CR>?<C-R>=@/<CR><CR>
function! s:VSetSearch()
let temp = @s
norm! gv"sy
let @/ = '\V' . substitute(escape(@s, '/\'), '\n', '\\n', 'g')
let @s = temp
endfunction
将上面的vim脚本粘贴到.vimrc
中,就可以使得*
和#
在可视模式下的语义附加上搜索选中内容这一项
第 14 章 替换
-
语法:
:[range]s[ubstitute]/{pattern}/{string}/[flags]
- 缺省情况下,
:s
命令仅仅作用于当前行的第一处匹配
- 缺省情况下,
-
[flags]
为标志位(:h s_flags
) -
替换域中的特殊字符
:h sub-replace-special
符号 描述 \r
插入一个换行符 \t
插入一个制表符 \\
插入一个反斜杠 \N
插入第N个子匹配,最多到\9 \0
插入匹配模式的所有内容 &
插入匹配模式的所有内容 ~
使用上一次 :s
命令的{string}
\={Vim Script}
执行 {Vim Script}
,并将结果作为{string}
-
控制每一次替换操作
-
若将substitute命令的查找域留空,则Vim会重用上次的查找模式
- 把查找域留空,会在命令历史中留下一项不完整的记录。这是由于模式通常保存在Vim的查找历史记录中,而substitute命令则保存于Ex命令的历史记录中
- ⭐️ 只需在命令行中输入
<C-r>/
,即可把上次的查找内容粘贴进来
-
可以将需要搜索的字符串复制到寄存器,通过传值或引用的方式将寄存器的内容应用至替换域。
- 传值
<C-r>{register}
,缺点是一些有特殊含义的字符没有处理 - 引用
\=@{register}
➾:let @/='Pragmatic Vim' ➾:let @a='Practical Vim' ➾:%s//\=@a/g
:let @/='Pragmatic Vim'
是采用编程的方式输入查找模式,它等同于/Pragmatic Vim<CR>
,但不会留下历史记录:let @a='Practical Vim'
设置 a 寄存器的内容。它等同于高亮选中“Practical Vim”并用"ay
将选中的文本存入寄存器 a。 - 传值
-
重复上一次substitute命令
-
&
用于重复上一次的替换操作,但是会忽略上次的标志位,可以用下面的映射把语义改成继承上次的标志位nnoremap & :&&<CR>
xnoremap & :&&<CR>
-
使用子匹配重排CSV文件的字段
last name,first name,email neil,drew,[email protected] doe,john,[email protected] ➾ /\v^([^,]*),([^,]*),([^,]*)$ ➾ :%s//\3,\2,\1 email,first name, last name ...
-
在替换过程中执行算术运算
例如将下面的标题都提升一级:
<h2>heading number 1</h2> <h3>Number 2 heading</h3> <h4>Another heading</h4>
-
交换两个或更多的单词
-
在多个文件中执行查找与替换
-
散射法(不管该文件中有没有匹配都执行):
:argdo %s//{string}/ge
,加上一个e
是因为有些文件里可能没有匹配,虽然并不会中止执行,但是会影响观感 -
点射法
➾ /Pragmatic\ze Vim ➾:vimgrep /<C-r>// **/*.txt ➾:argdo %s//Practical/g ➾:argdo update
vimgrep
命令是Vim内置的搜索引擎,上面的命令会让vimgrep
在当前目录及子目录下所有txt文件中进行搜索- 每个由
vimgrep
返回的匹配都将在quickfix
列表中被记录下来 - 将下面的脚本插入
.vimrc
中,即可通过:Qargs
命令把quikfix
列表加载到参数列表里
command! -nargs=0 -bar Qargs execute 'args' QuickfixFilenames() function! QuickfixFilenames() let buffer_numbers = {} for quickfix_item in getqflist() let buffer_numbers[quickfix_item['bufnr']] = bufname(quickfix_item['bufnr']) endfor return join(map(values(buffer_numbers), 'fnameescape(v:val)')) endfunction
-
第 15 章 global命令
-
global命令允许我们在某个指定模式的所有匹配行上运行 Ex 命令
-
global 和 delete 命令组合使用
-
:g//d
可以删掉特定匹配行 -
:v//d
删掉没匹配上的那些行例如下面的命令可以删掉所有带有xml标签的行
➾ /\v\<\/?\w+> ➾ :g//d
-
-
:global 和 :yank 命令结合使用
:g/{pattern}/yank A
- 注意寄存器要用大写的,表示附加而不是覆盖
- 通过这个方式,可以把一些行收集起来,比如收集所有的待办事项到一个寄存器里
- 也可以用
:g/{pattern}/t{address}
的方式,不放寄存器,直接粘贴在某个位置
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。