当前位置:   article > 正文

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

vim 查找
  • substitute,它允许我们查找某个模式的所有匹配,并用其他内容替换匹配结果
  • global,它让我们可以在匹配指定模式的所有行上执行任意的 Ex 命令
  • 精简的实用技巧:

1.按正则表达式查找时,使用 \v 模式开关
2.按原义查找文本时,使用 \V 原义开关
3.单词界定符,用 <> 符号表示单词定界符
4.统计当前模式的匹配个数(:%s///gn
5.技巧085:利用查找历史,迭代完成复杂的模式
6.技巧086:查找当前高亮选区中的文本


重要的事情说3遍:

笔记更新换位置了!
笔记更新换位置了!
笔记更新换位置了!

新位置:我写的新系列,刚开始写没几天,后续文章主要在新地址更新,欢迎支持;写作不易,且看且珍惜(点击跳转,欢迎收藏

按模式匹配和按原义匹配

技巧072:调整查找模式的大小写敏感性

我们既可以全局性地调整 Vim 查找功能的大小写敏感性,也可以在每次查找时进行局部调整

  • 全局设置大小写敏感性

启用ignorecase设置,Vim 的查找模式将不区分大小写(默认是noignorecase)

  • 每次查找时设置大小写敏感性(推荐

通过使用元字符 \c\C,可以覆盖Vim缺省的大小写敏感性设置;使用了两者中的某一个,ignorecase的值将被这次查找忽略

小写字母\c:会让查找模式忽略大小写

大写字母 \C:则会强制区分大小写

注意:这两个元字符可以出现在模式的任意位置

  • 启用更具智能的大小写敏感性设置

在这里插入图片描述

技巧073:按正则表达式查找时,使用 \v 模式开关

Vim 正则表达式的语法风格更接近 POSIX;通过使用 very magic 模式开关,就可以让 Vim 采用我们更为熟悉的正则表达式语法

示例:想要匹配css中一段颜色代码(匹配 1 个 # 字符以及紧随其后的 3 个或 6 个十六进制字符)

在这里插入图片描述

实现:常见的3种正则表达式命令比较如下

在这里插入图片描述

  • 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)的方式将光标移到该处

在这里插入图片描述

  • /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 会匹配空白符或换行符,这使得不在一行也能捕获到(收尾相同)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在这里插入图片描述

技巧076:界定单词的边界

在我们定义模式时,如果能指定单词从哪里开始到哪里结束的话,将会非常有用

示例:如果只想匹配单词the

  • 方法:使用/the<CR>会出现下面的情况,没有精确到我们想要的效果

在这里插入图片描述

  • 解决:可以使用单词界定符,用 <> 符号表示单词定界符;将查找命令改为 /\v<the><CR> (或者/\<the\><CR>也可以),文中就只会出现一处匹配了

提示1:以用 \W\ze\w 模拟元字符 <,而用 \w\ze\W 表示元字符 >

提示2:要想在 Vim 文档中查阅这些选项,我们得在前面附加一个斜杠,即:h /\<

技巧077:界定匹配的边界

我们可能想指定一个范围较广的模式,但只对匹配结果的一部分感兴趣。Vim 中的元字符 \zs\ze 可以帮助我们处理这种情况

# 元字符 \zs 标志着一个匹配的起始,而元字符 \ze 则用来界定匹配的结束
# 与单词定界符(前一节已介绍过)类似,\zs 与 \ze均为零宽度元字符(它们本身不匹配任何字符,
  仅表示单词与围绕此单词的空白字符(或标点符号)之间的边界)
  • 1
  • 2
  • 3

示例1:只有紧跟着单词“Practical”的“Vim”才会被高亮

在这里插入图片描述

示例2:同时使用 \zs 与 \ze 对匹配的起始与结尾进行微调

在这里插入图片描述

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

技巧078:转义问题字符

\V 原义开关使得按原义查找文本变得更容易,因为符号 .、+ 以及 * 的特殊含义被屏蔽掉了;但还有一些字符,其特殊含义无法被屏蔽

  • 示例:找到所有出现过http://vim-doc.net/search?q=/\\ 的地方

  • 思路:不必手动输入这些内容,只需将其复制到某个寄存器,然后再粘贴到查找域即可。由于我们想精确地匹配这段文本,因此要使用 \V 原义开关

  • 操作:光标位于方括号之中,就都可以使用命令 "uyi[(为了方便记忆,用 u 表示 URL)将此 URL 复制到寄存器 u。然后我们输入/\V<C-r>u<CR>,即可将此寄存器的内容填充至查找域了

知道这么多就可以了,后续的几个操作等有需要再总结吧…

  • 正向查找时要转义 / 字符

  • 反向查找时要转义?

  • 每次都要转义符号 \

  • 用编程的方式转义字符

查找

  • 首先,我们要掌握一些基础命令,怎样执行查找,如何高亮匹配以及怎样在各个匹配之间跳转
  • 然后,我们将学习几个基于 Vim 增量查找功能的技巧,它们不仅会为我们提供及时的反馈,而且会自动补全匹配,从而减少了按键次数
  • 另外,我们还将学习如何统计文档中匹配的个数(%s///gn

技巧079:结识查找命令

本节将涵盖查找命令的基础知识,包括怎样指定查找的方向,如何重复(或反向重复)上一次查找,以及怎样使用查找历史

在这里插入图片描述

  • 进入与回退

当我们按下 <CR> 键时,Vim 才会执行查找命令,而如果换用 <Esc> 键的话,查找提示符会消失,我们将重回普通模式

  • 回绕:不想绕回文档继续查找的话,可以关闭‘wrapscan’选项(参见 :h ‘wrapscan’)

  • 回溯之前的查找:当查找提示符出现时,我们可以通过 <Up> 键,滚动浏览之前的查找记录

技巧080:高亮查找匹配

Vim 可以高亮查找匹配,但该功能在缺省情况下没有被激活。我们将学到如何激活它,以及如何在已经高亮的情况下将其禁用

# 通过启用‘hlsearch’选项启动高亮
:set hlsearch
# 关闭高亮
:set nohealsearch
# 暂时关闭查找高亮功能,直到执行新的查找命令为止
:nohealsearch
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

技巧081:在执行查找前预览第一处匹配

缺省情况下,我们在输入查找模式时,Vim 不会进行查找;只有当我们按下 <CR> 后,它才会立即展开行动

命令::set incsearch:每当我们新输入一个字符时,Vim 会即时更新预览内容,效果就是实时高亮第一个匹配的内容

是否结束?

  • 如果此时我们按下 <Esc> 键,查找提示符将会消失,光标也将回退到位于行首的起始位置
  • 如果按 <CR> 执行这条命令的话,光标会跳转到匹配的内容(如果有的话)

扩展:检查是否有一处匹配?

假设只是想确认一个单词是否在文中有出现,但是却不想移动光标,前提是‘incsearch’选项被启用时即可;上面的介绍很适合这里,如果找到,只要<Esc>即可马上结束查找并返回原位

自动补全

假设我比较懒,查找"blocking",当输入block后就找到了结果,此时可以直接使用<C-r><C-w> ,此法会用当前预览的匹配结果对查找域进行自动补全(即直接将ing补上)

技巧082:统计当前模式的匹配个数

这则小技巧展示了如何统计某个模式的匹配个数

# :%s///gn
292 matches on 109 lines		--简单地统计匹配的次数

# 调用的是 :substitute 命令,但标志位 n 会抑制正常的替换动作
# 查找域:留空,旨在让 Vim 使用当前的查找模式
# 替换域:(由于标志位 n 的缘故)不管怎样都将会被忽略,因此也可以将其留空
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

技巧083:将光标偏移到查找匹配的结尾

我们将通过一个例子,研究如何将光标定位于匹配的结尾;Vim 的查找偏移功能,可以将此想法变为现实(参见 :h search-offset

示例:把所有出现 lang 的这 3 处地方扩展为完整的单词(language)

  • 常规思路:直接:%s/lang/language/g搞定

  • 复杂思路:复习一下前面学习的指令

在这里插入图片描述

详细解释

# 1.找到需要修改的字符串 /lang<CR> ,该命令把光标移到第一处匹配的起始位置
# 2.输入 eauage<Esc> ,即可在单词结尾添加新的内容
(e 正向移动到当前单词/下一个单词的结尾;a 切换到插入模式;ea:在当前单词结尾添加)
# 3.输入 ne.,我们可以修改下一处“lang”
(n 表示跳转至下一处匹配的起始位置,e 负责将光标移至单词结尾,而 . 会补全单词所需的字母)

# 上面操作合理?不合理,会将最后一个langs变成langsuage,出现问题了
# 解决:将第2步中的 ea 拆开,这样,每当我们使用 n 命令时,光标都会被定位于下一处查找匹配的结尾
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

技巧084:对完整的查找匹配进行操作

Vim 中,尽管匹配会被完整地高亮起来,但光标只会位于匹配的起始位置

如果我们想要操作模式匹配某个完整的单词,简单的可以使用eiw,复杂的就是本节要介绍的

  • 思路:构造一个可以匹配“Xml”或者“Xhtml”的正则表达式:/\vX(ht)?ml\C<CR> ,其中,元字符 \C 会强制区分大小写

  • 扩展:使用 gU{motion} 命令将一段文本转换为大写

暂时不介绍其他的了,平时用不到

技巧085:利用查找历史,迭代完成复杂的模式

撰写正则表达式是一件很难的事情,因为我们不可能一次就写对

下面总结一套顺畅的工作流程,允许我们通过迭代的方式逐步完成模式的设计工作

示例:将单词两侧的单引号变成双引号

This string contains a 'quoted' word. 
This string contains 'two' quoted 'words.' 
This 'string doesn't make things easy.'
  • 1
  • 2
  • 3

简单粗暴的替换会有问题,下面一步步展示正则表达式的写作思路

  • step1:粗糙匹配
# /\v'.+'
说明1:会首先匹配一个 ' 字符,然后匹配任意字符一次或多次,最终匹配另外一个 ' 字符
说明2.+ 项执行了贪婪匹配,其中: . 匹配一个字符(一定要有)
  • 1
  • 2
  • 3

在这里插入图片描述

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

在这里插入图片描述

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

最终形式:想捕获引号括起来的内容,加上一层括号会更好
# /\v'(([^']|'\w)+)'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述

扩展:不按 /<Up> 把上次的模式填到查找域,而是用 q/ 调出命令行窗口修改

在这里插入图片描述

目的:要理解还是有点不容易,为了复习前面知识,重点对c%(<C-r>")详细解释

实现效果:就是在[]左后两侧加()字符

  • c{motion} 命令:会删除指定的文本(覆盖无名寄存器),然后切换到插入模式
  • % 命令:允许我们在一组开、闭括号间跳转;(c%直接将内容剪切了)
  • <C-r>{register},其中{register}是我们想要插入的寄存器的名字; <C-r>"来插入无名寄存器的内容

一旦得到了理想模式,我们只需按下 <CR> 键即可执行查找了

  • step4:替换就完了
对于每一处匹配来说,引号所括的文本已经被赋给 \1 捕获寄存器了
# :%s//"\1"\/g
说明:将查找域留空,Vim 将重用上一次的查找命令
  • 1
  • 2
  • 3

最后,总结::%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/<C-R>"<CR> 
Note that special characters (like “.and*) will cause problems.
  • 1
  • 2
  • 3
  • 4

说明:vmap X y/<C-R>"<CR>,这个键盘映射能够将当前的选择区作为关键字进行搜索

y 命令会复制当前高亮选区的文本

/<C-r>"<CR> 调出查找提示符,并将无名寄存器的内容粘贴进来,执行查找命令

局限:某些特殊字符(例如 ‘.’ 和 ‘*’)可能会引起问题

  • 查找当前选中的文本(终极版

文件名:patterns/visual-star.vim ,你可以直接将这段代码粘贴至你的 vimrc 文件中,或者安装 visual star search 插件

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

参考

  • 《Vim实用技巧》
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/191838
推荐阅读
相关标签
  

闽ICP备14008679号