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


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

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

    按模式匹配和按原义匹配

    技巧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会出现下面的情况,没有精确到我们想要的效果

    在这里插入图片描述

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

    提示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。然后我们输入/\Vu,即可将此寄存器的内容填充至查找域了

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

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

    • 反向查找时要转义?

    • 每次都要转义符号 \

    • 用编程的方式转义字符

    查找

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

    技巧079:结识查找命令

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

    在这里插入图片描述

    • 进入与回退

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

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

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

    技巧080:高亮查找匹配

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

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

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

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

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

    是否结束?

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

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

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

    自动补全

    假设我比较懒,查找"blocking",当输入block后就找到了结果,此时可以直接使用 ,此法会用当前预览的匹配结果对查找域进行自动补全(即直接将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 ,该命令把光标移到第一处匹配的起始位置
    # 2.输入 eauage ,即可在单词结尾添加新的内容
    (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 ,其中,元字符 \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

    在这里插入图片描述

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

    在这里插入图片描述

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

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

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

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

    • 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/" 
    Note that special characters (like “.and*) will cause problems.
    
    • 1
    • 2
    • 3
    • 4

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

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

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

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

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

    文件名: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实用技巧》
  • 相关阅读:
    Linux之Vim编辑命令
    GPT-3在化学中进行低数据发现是否足够?
    web渗透工具
    自动化测试面试经历
    基于Asp.Net Core和Vue.js的Weblog系统的设计与实现
    高项 01 信息化与信息系统
    ​LeetCode解法汇总2651. 计算列车到站时间
    LeetCode1 两数之和
    阿里P8大牛发布《亿级流量并发手册》GitHub下载榜飙升至第一
    基于scikit-learn支持向量机(Support vector machine)的实现
  • 原文地址:https://blog.csdn.net/weixin_44531336/article/details/126219970