vim实用技巧|Vim实用技巧_7.模式匹配和查找

  • substitute,它允许我们查找某个模式的所有匹配,并用其他内容替换匹配结果
  • global,它让我们可以在匹配指定模式的所有行上执行任意的 Ex 命令
  • 精简的实用技巧:
1.按正则表达式查找时,使用 \v 模式开关
2.按原义查找文本时,使用 \V 原义开关
3.单词界定符,用 <> 符号表示单词定界符
4.统计当前模式的匹配个数(:%s///gn
5.技巧085:利用查找历史,迭代完成复杂的模式
6.技巧086:查找当前高亮选区中的文本

文章目录
  • 按模式匹配和按原义匹配
    • 技巧072:调整查找模式的大小写敏感性
    • 技巧073:按正则表达式查找时,使用 \v 模式开关
    • 技巧074:按`原义`查找文本时,使用 \V 原义开关
    • 技巧075:使用圆括号捕获子匹配
    • 技巧076:界定`单词`的边界
    • 技巧077:界定`匹配`的边界
    • 技巧078:转义问题字符
  • 查找
    • 技巧079:结识查找命令
    • 技巧080:`高亮`查找匹配
    • 技巧081:在执行查找前`预览`第一处匹配
    • 技巧082:统计当前模式的`匹配个数`
    • 技巧083:将光标`偏移`到查找匹配的结尾
    • 技巧084:对完整的查找匹配进行操作
    • 技巧085:利用查找历史,迭代完成复杂的模式
    • 技巧086:查找当前高亮选区中的文本
  • 参考

按模式匹配和按原义匹配 技巧072:调整查找模式的大小写敏感性
我们既可以全局性地调整 Vim 查找功能的大小写敏感性,也可以在每次查找时进行局部调整
  • 全局设置大小写敏感性
启用ignorecase设置,Vim 的查找模式将不区分大小写(默认是noignorecase)
  • 每次查找时设置大小写敏感性(推荐
通过使用元字符 \c\C,可以覆盖Vim缺省的大小写敏感性设置;使用了两者中的某一个,ignorecase的值将被这次查找忽略
小写字母\c:会让查找模式忽略大小写
大写字母 \C:则会强制区分大小写
注意:这两个元字符可以出现在模式的任意位置
  • 启用更具智能的大小写敏感性设置
vim实用技巧|Vim实用技巧_7.模式匹配和查找
文章图片

技巧073:按正则表达式查找时,使用 \v 模式开关
Vim 正则表达式的语法风格更接近 POSIX;通过使用 very magic 模式开关,就可以让 Vim 采用我们更为熟悉的正则表达式语法
示例:想要匹配css中一段颜色代码(匹配 1 个 # 字符以及紧随其后的 3 个或 6 个十六进制字符)
vim实用技巧|Vim实用技巧_7.模式匹配和查找
文章图片

实现:常见的3种正则表达式命令比较如下
vim实用技巧|Vim实用技巧_7.模式匹配和查找
文章图片

  • magic模式:处理圆括号,其他都要转
  • very magic模式:利用 \v 模式开关(会激活 very magic 搜索模式)来统一所有特殊符号的规则,假定除_大小写字母以及数字 0 到 9的所有字符都具有特殊含义
  • 十六进制字符类优化:用字符类 \x 代替完整的字符集[0-9a-fA-F]
说明:字符 # 没有特殊含义,因此可按原义匹配,这个在very magic模式暂时没有问题
但不意味着将来的版本也会这样。万一将来 # 被赋予了特殊含义,我们必须要将其转义后,才可以匹配“#”字符本身
技巧074:按原义查找文本时,使用 \V 原义开关
通用法则:如果想按正则表达式查找,就用模式开关 \v,而如果想按原义查找文本,就用原义开关 \V
示例:想通过查找“a.k.a.”(此缩写表示 also known as)的方式将光标移到该处
vim实用技巧|Vim实用技巧_7.模式匹配和查找
文章图片

  • /a.k.a. :匹配的内容要多很多,是因为符号“.”具有特殊含义。它匹配任意字符
扩展::substitute 命令的查找域留空,Vim 将使用上一次的查找模式(如::%s//also?known?as/g
  • \V:使用 “\V” 会使得其后的模式中只有反斜杠有特殊的意义
技巧075:使用圆括号捕获子匹配
当我们指定一个模式时,可以捕获其子匹配,并在其他地方引用它们;有时间的话,可以多看看pattern.txt的内容
示例:有一个专门用来匹配重复单词的正则表达式
# /\v<(\w+)\_s+\1> 说明:能两次匹配相同的单词,诀窍就在于 () 与 \1 的组合使用# () 与 \1 说明 - 1.任何圆括号内部的匹配文本都会被 自动 保存到一个临时的仓库 - 2.可以用 \1 引用这段被捕获的文本;不止一组圆括号,则可以用 \1、\2,直到 \9,引用被 每对 () 捕获的子匹配 - 3.不论模式中是否使用了圆括号,元字符 \0 永远会引用整个匹配# \v 模式开关会激活 very magic 搜索模式(字符有特殊意义) # < 与 > 两符号将用于匹配单词的边界 # \w 匹配单词类字符,包括字母、数字以及符号“_”,\W 则用来匹配除单词类字符以外的其他字符 # 元字符 \_s 会匹配空白符或换行符,这使得不在一行也能捕获到(收尾相同)

vim实用技巧|Vim实用技巧_7.模式匹配和查找
文章图片

技巧076:界定单词的边界
在我们定义模式时,如果能指定单词从哪里开始到哪里结束的话,将会非常有用
示例:如果只想匹配单词the
  • 方法:使用/the会出现下面的情况,没有精确到我们想要的效果
vim实用技巧|Vim实用技巧_7.模式匹配和查找
文章图片

  • 解决:可以使用单词界定符,用 <> 符号表示单词定界符;将查找命令改为 /\v (或者/\也可以),文中就只会出现一处匹配了
提示1:以用 \W\ze\w 模拟元字符 <,而用 \w\ze\W 表示元字符 >
提示2:要想在 Vim 文档中查阅这些选项,我们得在前面附加一个斜杠,即:h /\<
技巧077:界定匹配的边界
我们可能想指定一个范围较广的模式,但只对匹配结果的一部分感兴趣。Vim 中的元字符 \zs\ze 可以帮助我们处理这种情况
# 元字符 \zs 标志着一个匹配的起始,而元字符 \ze 则用来界定匹配的结束 # 与单词定界符(前一节已介绍过)类似,\zs 与 \ze均为零宽度元字符(它们本身不匹配任何字符, 仅表示单词与围绕此单词的空白字符(或标点符号)之间的边界)

示例1:只有紧跟着单词“Practical”的“Vim”才会被高亮
vim实用技巧|Vim实用技巧_7.模式匹配和查找
文章图片

示例2:同时使用 \zs 与 \ze 对匹配的起始与结尾进行微调
vim实用技巧|Vim实用技巧_7.模式匹配和查找
文章图片

# "[^"]+" 该模式使用两个引号作为起始与结尾的标记,然后匹配除引号之外的一个或多个字符

技巧078:转义问题字符
\V 原义开关使得按原义查找文本变得更容易,因为符号 .、+ 以及 * 的特殊含义被屏蔽掉了;但还有一些字符,其特殊含义无法被屏蔽
  • 示例:找到所有出现过http://vim-doc.net/search?q=/\\ 的地方
  • 【vim实用技巧|Vim实用技巧_7.模式匹配和查找】思路:不必手动输入这些内容,只需将其复制到某个寄存器,然后再粘贴到查找域即可。由于我们想精确地匹配这段文本,因此要使用 \V 原义开关
  • 操作:光标位于方括号之中,就都可以使用命令 "uyi[(为了方便记忆,用 u 表示 URL)将此 URL 复制到寄存器 u。然后我们输入/\Vu,即可将此寄存器的内容填充至查找域了
知道这么多就可以了,后续的几个操作等有需要再总结吧…
  • 正向查找时要转义 / 字符
  • 反向查找时要转义?
  • 每次都要转义符号 \
  • 用编程的方式转义字符
查找
  • 首先,我们要掌握一些基础命令,怎样执行查找,如何高亮匹配以及怎样在各个匹配之间跳转
  • 然后,我们将学习几个基于 Vim 增量查找功能的技巧,它们不仅会为我们提供及时的反馈,而且会自动补全匹配,从而减少了按键次数
  • 另外,我们还将学习如何统计文档中匹配的个数(%s///gn
技巧079:结识查找命令
本节将涵盖查找命令的基础知识,包括怎样指定查找的方向,如何重复(或反向重复)上一次查找,以及怎样使用查找历史
vim实用技巧|Vim实用技巧_7.模式匹配和查找
文章图片

  • 进入与回退
当我们按下 键时,Vim 才会执行查找命令,而如果换用 键的话,查找提示符会消失,我们将重回普通模式
  • 回绕:不想绕回文档继续查找的话,可以关闭‘wrapscan’选项(参见 :h ‘wrapscan’)
  • 回溯之前的查找:当查找提示符出现时,我们可以通过 键,滚动浏览之前的查找记录
技巧080:高亮查找匹配
Vim 可以高亮查找匹配,但该功能在缺省情况下没有被激活。我们将学到如何激活它,以及如何在已经高亮的情况下将其禁用
# 通过启用‘hlsearch’选项启动高亮 :set hlsearch # 关闭高亮 :set nohealsearch # 暂时关闭查找高亮功能,直到执行新的查找命令为止 :nohealsearch

技巧081:在执行查找前预览第一处匹配
缺省情况下,我们在输入查找模式时,Vim 不会进行查找;只有当我们按下 后,它才会立即展开行动
命令::set incsearch:每当我们新输入一个字符时,Vim 会即时更新预览内容,效果就是实时高亮第一个匹配的内容
是否结束?
  • 如果此时我们按下 键,查找提示符将会消失,光标也将回退到位于行首的起始位置
  • 如果按 执行这条命令的话,光标会跳转到匹配的内容(如果有的话)
扩展:检查是否有一处匹配?
假设只是想确认一个单词是否在文中有出现,但是却不想移动光标,前提是‘incsearch’选项被启用时即可;上面的介绍很适合这里,如果找到,只要即可马上结束查找并返回原位
自动补全
假设我比较懒,查找"blocking",当输入block后就找到了结果,此时可以直接使用 ,此法会用当前预览的匹配结果对查找域进行自动补全(即直接将ing补上)
技巧082:统计当前模式的匹配个数
这则小技巧展示了如何统计某个模式的匹配个数
# :%s///gn 292 matches on 109 lines--简单地统计匹配的次数# 调用的是 :substitute 命令,但标志位 n 会抑制正常的替换动作 # 查找域:留空,旨在让 Vim 使用当前的查找模式 # 替换域:(由于标志位 n 的缘故)不管怎样都将会被忽略,因此也可以将其留空

技巧083:将光标偏移到查找匹配的结尾
我们将通过一个例子,研究如何将光标定位于匹配的结尾;Vim 的查找偏移功能,可以将此想法变为现实(参见 :h search-offset
示例:把所有出现 lang 的这 3 处地方扩展为完整的单词(language)
  • 常规思路:直接:%s/lang/language/g搞定
  • 复杂思路:复习一下前面学习的指令
vim实用技巧|Vim实用技巧_7.模式匹配和查找
文章图片

详细解释
# 1.找到需要修改的字符串 /lang ,该命令把光标移到第一处匹配的起始位置 # 2.输入 eauage ,即可在单词结尾添加新的内容 (e 正向移动到当前单词/下一个单词的结尾;a 切换到插入模式;ea:在当前单词结尾添加) # 3.输入 ne.,我们可以修改下一处“lang” (n 表示跳转至下一处匹配的起始位置,e 负责将光标移至单词结尾,而 . 会补全单词所需的字母)# 上面操作合理?不合理,会将最后一个langs变成langsuage,出现问题了 # 解决:将第2步中的 ea 拆开,这样,每当我们使用 n 命令时,光标都会被定位于下一处查找匹配的结尾

技巧084:对完整的查找匹配进行操作
Vim 中,尽管匹配会被完整地高亮起来,但光标只会位于匹配的起始位置
如果我们想要操作模式匹配某个完整的单词,简单的可以使用eiw,复杂的就是本节要介绍的
  • 思路:构造一个可以匹配“Xml”或者“Xhtml”的正则表达式:/\vX(ht)?ml\C ,其中,元字符 \C 会强制区分大小写
  • 扩展:使用 gU{motion} 命令将一段文本转换为大写
暂时不介绍其他的了,平时用不到
技巧085:利用查找历史,迭代完成复杂的模式
撰写正则表达式是一件很难的事情,因为我们不可能一次就写对
下面总结一套顺畅的工作流程,允许我们通过迭代的方式逐步完成模式的设计工作
示例:将单词两侧的单引号变成双引号
This string contains a 'quoted' word. This string contains 'two' quoted 'words.' This 'string doesn't make things easy.'

简单粗暴的替换会有问题,下面一步步展示正则表达式的写作思路
  • step1:粗糙匹配
# /\v'.+' 说明1:会首先匹配一个 ' 字符,然后匹配任意字符一次或多次,最终匹配另外一个 ' 字符 说明2:.+ 项执行了贪婪匹配,其中: . 匹配一个字符(一定要有)

vim实用技巧|Vim实用技巧_7.模式匹配和查找
文章图片

  • step2:不用那个匹配任意字符的 . 符号
说明:要匹配的是除了 ' 之外的任意字符,因此可以用 [^']+ 提示:只需按 /,查找域中便会出现上一次的模式,在上面修改即可 # /\v'[^']+'

vim实用技巧|Vim实用技巧_7.模式匹配和查找
文章图片

  • step3.接近成功了,修复第三行的问题
撇号与闭引号的区别到底是什么? 撇号后面紧跟着某个字母 # /\v'([^']|'\w)+'1 说明:不仅额外增加了元字符 '\w,而且还将两种可选方案用括号括了起来并用竖线隔开最终形式:想捕获引号括起来的内容,加上一层括号会更好 # /\v'(([^']|'\w)+)'

vim实用技巧|Vim实用技巧_7.模式匹配和查找
文章图片

扩展:不按 / 把上次的模式填到查找域,而是用 q/ 调出命令行窗口修改
vim实用技巧|Vim实用技巧_7.模式匹配和查找
文章图片

目的:要理解还是有点不容易,为了复习前面知识,重点对c%(")详细解释
实现效果:就是在[]左后两侧加()字符
  • c{motion} 命令:会删除指定的文本(覆盖无名寄存器),然后切换到插入模式
  • % 命令:允许我们在一组开、闭括号间跳转;(c%直接将内容剪切了)
  • {register},其中{register}是我们想要插入的寄存器的名字; "来插入无名寄存器的内容
一旦得到了理想模式,我们只需按下 键即可执行查找了
  • step4:替换就完了
对于每一处匹配来说,引号所括的文本已经被赋给 \1 捕获寄存器了 # :%s//"\1"\/g 说明:将查找域留空,Vim 将重用上一次的查找命令

最后,总结::%s/\v'(([^']|'\w)+)'/"\1"/g
技巧086:查找当前高亮选区中的文本
在普通模式下,* 命令让我们可以查找光标下的单词
通过一小段 Vim 脚本,重新定义可视模式下的 * 命令,使其可以查找当前选中的文本,而不是光标下的单词
  • 查找当前选中的文本(现有技术
# 查询 :h visual-search ,会发现这样一条建议: Here is an idea for a mapping that makes it possible to do a search for the selected text: # :vmap X y/" Note that special characters (like “.” and “*”) will cause problems.

说明::vmap X y/",这个键盘映射能够将当前的选择区作为关键字进行搜索
y 命令会复制当前高亮选区的文本
/" 调出查找提示符,并将无名寄存器的内容粘贴进来,执行查找命令
局限:某些特殊字符(例如 ‘.’ 和 ‘*’)可能会引起问题
  • 查找当前选中的文本(终极版
文件名:patterns/visual-star.vim ,你可以直接将这段代码粘贴至你的 vimrc 文件中,或者安装 visual star search 插件
xnoremap * :call >VSetSearch()/=@/ xnoremap # :call >VSetSearch()?=@/ function! s:VSetSearch() let temp = @s norm! gv"sy let @/ = '\V' . substitute(escape(@s, '/\'), '\n', '\\n', 'g') let @s = temp endfunction

说明:在上面的脚本中,不仅 * 命令的原有功能被覆盖了,# 命令也被重新定义为反向查找选中的文本了。xnoremap 关键字指明此映射项只在可视模式下有效,不包括选择模式
参考
  • 《Vim实用技巧》

    推荐阅读