Vim 学习笔记 No.6
模式匹配,查找和替换
复习 / 预习正则表达式
vim 中的正则表达式和我之前学过的不太一样诶~
1 调整查找模式的大小写敏感性
先推荐使用如下 vimrc 配置
" 大小写设置
set ignorecase
set infercase
set smartcase
大致功能为:忽略大小写、自动补全时保持已输入字母的大小写、搜索时部分推断是否区分大小写。
具体功能见帮助文档,不再赘述。
如果要强制不区分大小写,可以在模式串中任意位置加上 \c。类似的,\C 强制不区分大小写。
2 特殊字符的转义
众所周知,正则表达式中有部分字符具有特殊含义,而不会被按照原意匹配。然而 vim 对于这些字符的默认处理方法各不相同,有的默认按原意,有的默认按照特殊字符处理。
在模式串中加入 \v,默认将其后的 『除 _ 、 字母 数字 以外的』 字符当作特殊字符处理,若想要按照原意匹配,需用 \ 转义。使用 \V 得到相反的效果。
实际上,不是所有的符号都需要转义才能进行原字符匹配,仅目前用作特殊字符的那些才一定需要
注意 是其后的字符!!!假如使用/\V### \v[0-9]对本 md 文档进行匹配,是可以匹配到『### 2 』等字符的。
有些字符必须转义
在前向查找中,必须要转义/,反向查找中,必须要转义?。每次都必须转义\ 。
可用编程的方式转义,如:escape({pattern}, '/\'),具体用法见:h escape()
3 值得注意的元字符
- \s 匹配空格和 tab 符,_s 匹配空格 tab 符和换行符
- 使用 < 和 > 可标记单词前后边界
- \zs \ze 标记匹配部分的开始和结尾,即可对模式串进行部分匹配(类似于标准的正则表达式中 lookground 模式吧)
- \e 使查找后光标移动到这个位置
4 使用圆括号但不捕获内容
在圆括号前加上 %
查找
1 n 与 N
n查找下一处匹配,N查找上一处。但这里的上下取决于是用/还是用?进行的查找。输入/<CR>复用上一次的模式串,但改用正向查找。?<CR>同理。
2 查找高亮
建议使用一下配置(记不得在哪个地方抄的了
" 当光标一段时间保持不动了,就禁用高亮
autocmd cursorhold * set nohlsearch
" 当输入查找命令时,再启用高亮
noremap n :set hlsearch<cr>n
noremap N :set hlsearch<cr>N
noremap / :set hlsearch<cr>/
noremap ? :set hlsearch<cr>?
noremap * *:set hlsearch<cr>
书上还建议了手动关闭高亮的设置,感觉挺好用
" <C-l>手动关闭高亮
nnoremap <silent> <C-l> :<C-u>nohlsearch<CR><C-l>
3 即时显示搜索结果
一边输入模式串,一边即时搜索,听起来就很棒棒不是吗?加入以下配置
" 搜索的同时即时显示结果
set incsearch
同时可以利用<C-r><C-w>利用搜索结果补全模式串~
4 统计当前模式的匹配个数
使用:%s///gn可以统计当前匹配的个数。书中把为这条命令创建映射项的任务作为练习了,一个参考做法如下:
" 按下 <leader>n 统计匹配个数
nnoremap <leader>n :set hlsearch<CR>:%s///gn<CR><C-o>
5 查找选定文本
书上给出了一段代码:
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
- 为什么要使用
=@/ 而不是 / 呢?因为后者可能会将 / 寄存器中的某些字符看作特殊字符。 *
另外也给出了作者写的插件,我当然选择使用插件(毕竟无脑多了 github 地址 ,使用 Vundle 安装的方法自行百度。不过写脚本的方法值得参考学习,因此还是记录下来。
替换
命令的一般形式
[range]s[ubstitute]/{pattern}/{string}/[flags]
1 替换域中值得注意的特殊字符
- \r \t 换行符和制表符(学过 C 语言的都知道吧)注意 \n 在 vim 有特别的含义
- [1-9] 指代某个子匹配
- \0 或者 & 指代整个字符串
- ~ 使用上一次替换时使用的{string}
- ={Vim script} 执行表达式并转换为字符串
2 标志位
- g 全局执行,即修改一行内所有的匹配
- c 确认或拒绝每一处修改
- n 抑制正常的替换而报告匹配个数
- e 屏蔽执行错误
- & 重用上一次的标志位
3 替换的流程
一个建议流程是先使用查找模式测试模式串,模式串正常工作后使用替换,并将模式串部分留空,即可使用上次查找的模式串进行匹配了。
不过在历史记录中,用这种形式做的替换想要重用时会遇到麻烦。因此可以使用
4 重复上一次的 substitute 命令
:&将重复上一次的替换命令,但忽视标志位和范围。:&&将同时重复标志位。
g&命令在每一行重复上一次的替换命令,相当于:%&&的快捷方式。
5 超级替换
多余的话就省了,直接推荐 Abolish 插件,提供:S命令,可以进行更高级的替换功能,还能使用自动缩写替换等有趣的功能。
global 命令
一般形式:[range] g[lobal][!] /{pattern}/ {cmd}
global 命令可以对匹配模式串的每一行执行 Ex 命令,其中{pattern}缺省使用查找中的模式串,{cmd} 默认使用print,范围默认为全文件。
使用global!或者vglobal对未匹配模式串的每一行执行命令。
以下是几个应用实例:
1 收集 TODO 项
代码中经常需要四处留下 TODO 标记,用:g/TODO可以快速显示含有 TODO 的每一行。进一步,还能把这些行放置在某个寄存器中:
先使用q{register}q清空某个寄存器,比如 a 寄存器: qaq 。接着执行 :g/TODO/y A即可放入寄存器中。
2 按字母排序
:sort可以对选中部分文本进行排序。
若要对 css 文件中所有大括号内的文本排序,可用 :g/{/ .+1,/}/-1 sort。这条命令中,:g/{/查找所有的左大括号,.代表查找结果所在行,/}/匹配右大括号,+1和-1是偏移量。
从中可总结出:global命令的广义形式
:g/{start}/ .,{finish} {cmd}