赞
踩
- substitute,它允许我们查找某个模式的所有匹配,并用其他内容替换匹配结果
- global,它让我们可以在匹配指定模式的所有行上执行任意的 Ex 命令
- 精简的实用技巧:
1.按
正则表达式
查找时,使用\v
模式开关
2.按原义
查找文本时,使用\V
原义开关
3.单词界定符,用<
与>
符号表示单词定界符
4.统计当前模式的匹配个数(:%s///gn
)
5.技巧085:利用查找历史,迭代完成复杂的模式
6.技巧086:查找当前高亮选区中的文本
重要的事情说3遍:
笔记更新换位置了!
笔记更新换位置了!
笔记更新换位置了!
新位置
:我写的新系列,刚开始写没几天,后续文章主要在新地址更新,欢迎支持;写作不易,且看且珍惜(点击跳转,欢迎收藏)
我们既可以全局性地调整 Vim 查找功能的大小写敏感性,也可以在每次查找时进行局部调整
- 全局设置大小写敏感性
启用
ignorecase
设置,Vim 的查找模式将不区分大小写(默认是noignorecase)
- 每次查找时设置大小写敏感性(
推荐
)通过使用元字符
\c
与\C
,可以覆盖Vim缺省的大小写敏感性设置;使用了两者中的某一个,ignorecase
的值将被这次
查找忽略小写字母
\c
:会让查找模式忽略大小写大写字母
\C
:则会强制区分大小写注意:这两个元字符可以出现在模式的任意位置
- 启用更具智能的大小写敏感性设置
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模式暂时没有问题但不意味着将来的版本也会这样。万一将来
#
被赋予了特殊含义,我们必须要将其转义后,才可以匹配“#”字符本身
原义
查找文本时,使用 \V 原义开关通用法则:如果想按正则表达式查找,就用模式开关
\v
,而如果想按原义查找文本,就用原义开关\V
示例:想通过查找“a.k.a.”(此缩写表示 also known as)的方式将光标移到该处
/a.k.a.
:匹配的内容要多很多,是因为符号“.
”具有特殊含义。它匹配任意字符扩展:
:substitute
命令的查找域留空
,Vim 将使用上一次的查找模式
(如::%s//also␣known␣as/g
)
\V
:使用 “\V
” 会使得其后的模式中只有反斜杠有特殊的意义
当我们指定一个模式时,可以捕获其子匹配,并在其他地方引用它们;有时间的话,可以多看看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
单词
的边界在我们定义模式时,如果能指定单词从哪里开始到哪里结束的话,将会非常有用
示例:如果只想匹配单词
the
- 方法:使用
/the<CR>
会出现下面的情况,没有精确到我们想要的效果
- 解决:可以使用单词界定符,用
<
与>
符号表示单词定界符;将查找命令改为/\v<the><CR>
(或者/\<the\><CR>
也可以),文中就只会出现一处匹配了提示1:以用
\W\ze\w
模拟元字符<
,而用\w\ze\W
表示元字符>
提示2:要想在 Vim 文档中查阅这些选项,我们得在前面附加一个斜杠,即
:h /\<
匹配
的边界我们可能想指定一个范围较广的模式,但只对匹配结果的一部分感兴趣。Vim 中的元字符
\zs
与\ze
可以帮助我们处理这种情况# 元字符 \zs 标志着一个匹配的起始,而元字符 \ze 则用来界定匹配的结束 # 与单词定界符(前一节已介绍过)类似,\zs 与 \ze均为零宽度元字符(它们本身不匹配任何字符, 仅表示单词与围绕此单词的空白字符(或标点符号)之间的边界)
- 1
- 2
- 3
示例1:只有紧跟着单词“Practical”的“Vim”才会被高亮
示例2:同时使用 \zs 与 \ze 对匹配的起始与结尾进行微调
# "[^"]+" 该模式使用两个引号作为起始与结尾的标记,然后匹配除引号之外的一个或多个字符
- 1
\V
原义开关使得按原义查找文本变得更容易,因为符号 .、+ 以及 * 的特殊含义被屏蔽掉了;但还有一些字符,其特殊含义无法被屏蔽
示例:找到所有出现过
http://vim-doc.net/search?q=/\\
的地方思路:不必手动输入这些内容,只需将其复制到某个寄存器,然后再粘贴到查找域即可。由于我们想精确地匹配这段文本,因此要使用
\V
原义开关操作:光标位于方括号之中,就都可以使用命令
"uyi[
(为了方便记忆,用u
表示 URL)将此 URL 复制到寄存器u
。然后我们输入/\V<C-r>u<CR>
,即可将此寄存器的内容填充至查找域了知道这么多就可以了,后续的几个操作等有需要再总结吧…
正向查找时要转义
/
字符反向查找时要转义
?
号每次都要转义符号
\
用编程的方式转义字符
- 首先,我们要掌握一些基础命令,怎样执行查找,如何高亮匹配以及怎样在各个匹配之间跳转
- 然后,我们将学习几个基于 Vim 增量查找功能的技巧,它们不仅会为我们提供及时的反馈,而且会自动补全匹配,从而减少了按键次数
- 另外,我们还将学习如何统计文档中匹配的个数(
%s///gn
)
本节将涵盖查找命令的基础知识,包括怎样指定查找的方向,如何重复(或反向重复)上一次查找,以及怎样使用查找历史
- 进入与回退
当我们按下
<CR>
键时,Vim 才会执行查找命令,而如果换用<Esc>
键的话,查找提示符会消失,我们将重回普通模式
回绕:不想绕回文档继续查找的话,可以关闭‘wrapscan’选项(参见 :h ‘wrapscan’)
回溯之前的查找:当查找提示符出现时,我们可以通过
<Up>
键,滚动浏览之前的查找记录
高亮
查找匹配Vim 可以高亮查找匹配,但该功能在缺省情况下没有被激活。我们将学到如何激活它,以及如何在已经高亮的情况下将其禁用
# 通过启用‘hlsearch’选项启动高亮 :set hlsearch # 关闭高亮 :set nohealsearch # 暂时关闭查找高亮功能,直到执行新的查找命令为止 :nohealsearch
- 1
- 2
- 3
- 4
- 5
- 6
预览
第一处匹配缺省情况下,我们在输入查找模式时,Vim 不会进行查找;只有当我们按下
<CR>
后,它才会立即展开行动命令:
:set incsearch
:每当我们新输入一个字符时,Vim 会即时更新预览内容,效果就是实时高亮第一个匹配的内容是否结束?
- 如果此时我们按下
<Esc>
键,查找提示符将会消失,光标也将回退到位于行首的起始位置- 如果按
<CR>
执行这条命令的话,光标会跳转到匹配的内容(如果有的话)扩展:检查是否有一处匹配?
假设只是想确认一个单词是否在文中有出现,但是却不想移动光标,前提是‘incsearch’选项被启用时即可;上面的介绍很适合这里,如果找到,只要
<Esc>
即可马上结束查找并返回原位自动补全
假设我比较懒,查找"blocking",当输入block后就找到了结果,此时可以直接使用
<C-r><C-w>
,此法会用当前预览的匹配结果对查找域进行自动补全(即直接将ing补上)
匹配个数
这则小技巧展示了如何统计某个模式的匹配个数
# :%s///gn 292 matches on 109 lines --简单地统计匹配的次数 # 调用的是 :substitute 命令,但标志位 n 会抑制正常的替换动作 # 查找域:留空,旨在让 Vim 使用当前的查找模式 # 替换域:(由于标志位 n 的缘故)不管怎样都将会被忽略,因此也可以将其留空
- 1
- 2
- 3
- 4
- 5
- 6
偏移
到查找匹配的结尾我们将通过一个例子,研究如何将光标定位于匹配的结尾;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
Vim 中,尽管匹配会被完整地高亮起来,但光标只会位于匹配的起始位置
如果我们想要操作模式匹配某个完整的单词,简单的可以使用
e
或iw
,复杂的就是本节要介绍的
思路:构造一个可以匹配“Xml”或者“Xhtml”的正则表达式:
/\vX(ht)?ml\C<CR>
,其中,元字符\C
会强制区分大小写扩展:使用
gU{motion}
命令将一段文本转换为大写暂时不介绍其他的了,平时用不到
撰写正则表达式是一件很难的事情,因为我们不可能一次就写对
下面总结一套顺畅的工作流程,允许我们通过迭代的方式逐步完成模式的设计工作
示例:将单词两侧的单引号变成双引号
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
在普通模式下,
*
命令让我们可以查找光标下的单词通过一小段 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
关键字指明此映射项只在可视模式下有效,不包括选择模式
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。