07|正则表达式:实现文件内容的搜索和替换
该思维导图由 AI 生成,仅供参考
正则表达式搜索
- 深入了解
- 翻译
- 解释
- 总结
Vim 正则表达式搜索和替换技巧 Vim 中的正则表达式在文件内容的搜索和替换中发挥着重要作用。本文详细介绍了在 Vim 中使用正则表达式进行搜索和替换的基本方法和特点。通过 `/` 和 `:s` 命令,读者可以学习如何利用正则表达式进行文件内容的查找和替换。文章深入讲解了搜索模式中的特殊字符和其含义,以及如何使用特殊模式项进行高效的匹配。此外,还分享了一些实际的搜索实例,帮助读者更好地理解正则表达式的应用。 在替换部分,文章介绍了一些复杂的替换情况,包括保留匹配中的某些字符、大小写转换、计算替换结果等。还详细讲解了在替换字符串中引用前面匹配内容的方法,以及 Vim 中的特殊替换字符串和标志的使用。通过实例演示,读者可以更好地掌握 Vim 中正则表达式替换的技巧。 总的来说,本文内容密集,但重点突出。读者可以通过本文快速了解 Vim 中正则表达式的基本知识,提高文件内容处理的效率。文章内容丰富,建议读者多加练习,以便更好地掌握正则表达式搜索和替换的技巧。
《Vim 实用技巧必知必会》,新⼈⾸单¥59
全部留言(16)
- 最新
- 精选
- 我来也课后练习: # 1. 如果要搜索“/* */”注释的话 参考文中的替换正则表达式(第一个`:`是命令行模式的前缀,执行时不需要贴入.) ``` :%s!/\*\_.\{-}\*/!!g ``` 稍作修改即可(第一个`/`是查找命令的前缀,搜索时不需要贴入.) ``` /\/\*\_.\{-}\*\/ ``` # 2. 把 begin_search_nocase 这样的函数名称转变成 BeginSearchNocase 可以分两步走: 1. 使用文中的命令,将首字母替换成大写 ``` %s/\<\(_*\)\([a-z]\w*\)\ze(/\1\u\2/g ``` 2. 将函数名中`_`后面的字符替换成大写: ``` %s/\<_*[A-Z]\zs\(\w*\)\ze(/\=substitute(submatch(1),'_\+\(\w\)','\=toupper(submatch(1))','g')/g ``` 测试用例 替换前: ``` begin_search_nocase() beGin_seaRch_noCase() _beGin_seaRch_nocase_100_() ``` 替换后: ``` BeginSearchNocase() BeGinSeaRchNoCase() _BeGinSeaRchNocase100_() ``` 3. 两步合一步的搞法:(不太推荐) ``` %s/\<_*\zs\([a-zA-Z]\w*\)\ze(/\=substitute(substitute(submatch(1),'^','_',''),'_\+\(\w\)','\=toupper(submatch(1))', 'g')/g ``` a. 使用`\zs\([a-zA-Z]\w*\)\ze(`找到函数名的边界 b. 将提取出来的名称添加前缀`_`,方便后面的替换.`substitute(submatch(1),'^','_','')` c. 将名称中`_`后面的字符替换成大写.`substitute('步骤b返回的结果','_\+\(\w\)','\=toupper(submatch(1))', 'g')` 4. 测试用例单词中间的大写字母并没变,按理说是需要变成小写的. 这个正则可以做到: ``` %s/\<_*\zs\([a-zA-Z]\w*\)\ze(/\=substitute(substitute(submatch(1),'\C\(_\)\=\(.\)','\=submatch(1)==""?tolower(submatch(2)) : toupper(submatch(2))', 'g'),'^.','\u&', 'g')/g ``` 实现的效果是: ``` BeginSearchNocase() BeginSearchNocase() _BeginSearchNocase100_() ``` # 开心的带货环节 强烈推荐一个vim中多光标的插件 [vim-visual-multi](https://github.com/mg979/vim-visual-multi) 我以前都是用`.`命令,或者宏来实现类似的效果,但是并不直观和方便. 第四个正则并不是我想到的,我只是把插件[vim-visual-multi](https://github.com/mg979/vim-visual-multi/blob/cb994375fcbf032adfef6d31d8fcfa59bab381c8/autoload/vm/special/case.vim#L22-L34) 中的代码拿来改了一下. 这个插件可以在vim中实现多光标编辑,实现Sublime中的那种效果. 我觉得比Sublime中的多行编辑还厉害多了. 就连7.5k stars的[vim-multiple-cursors](https://github.com/terryma/vim-multiple-cursors)都推荐使用`vim-visual-multi`. 可惜谷歌上都无法搜索到该插件的中文介绍. -- 如果是课后练习2中的需求,使用该插件,就非常非常简单了. 1. 在搜索命令中查找要匹配的函数名:(第一个`/`不需要贴入) ``` /\<_*\zs[a-zA-Z]\w*\ze( ``` 2. 在普通模式中全选文件内容 `ggVG` 3. 用插件的多光标来选中上次搜索的内容`<leader><leader>f` 4. 唤出插件的字符转换功能`<leader><leader>C` [:help vm-case-conversion] 有很多种转换规则,下划线转驼峰只是其中的一个功能. 5. 使用其中的`P`选项即可实现效果.
作者回复: 就属你最牛了。这回我都了解了些新东西。😝
2020-08-0713 - 我来也# 又是一篇非常全面的课程. 如果是0基础的人看了,估计就要入门到放弃了.哈哈. 正则本身就有点小复杂,再加上vi中有些模式跟主流的还不太一样. # 今天学到的新知识: 在正则中,我之前虽然也知道vim有贪婪模式和最短匹配,但是真没细究过. 今天看了老师的`<.\{-1,}>`和`:%s!/\*\_.\{-}\*/!!g`,才知道这东西写起来也不复杂. 具体的可以查看帮助: `:help /multi` \{-} \{-} 0 或更多 尽可能少 # 我介绍下搜索中,我非常常用的特殊模式项: `\c` : 强制忽略大小消息 `\C` : 强制开启大消息匹配 (`\v`和`\V`用的不多,但知道是怎么回事.) 另外,我一般会开启搜索相关的两个选项: set ignorecase " Case insensitive search set smartcase " Case sensitive when uc present 忽略大消息 和 智能大小写. 在查询的内容中有大写字母时,就区分大小写,否则就是不区分. 在确定只需要查询小写字母时,需要在搜索模式中加上`\c`. # 补充下普通模式下的全字匹配光标所在的关键字 向后搜索 `*` : 是全字匹配,会在搜索关键字前后自动添加`\<`和`\>` `g*`: 不开启全字匹配,不自动添加`\<`和`\>` 对应的还有 向前搜索 `#` : 全字匹配 `g#`: 不开启全字匹配 vim中的命令繁多,还是配套起来记记得更牢. # 对于取消搜索高亮,我也有这种需求. 我也是映射了快捷键,但只映射了普通模式的,没有映射插入模式的. 我的方式是在普通模式下,按删除键时,附带的取消高亮. nnoremap <silent> <BS> <BS>:nohlsearch<CR> 我也见过用如下按键映射的: nnoremap <silent> <leader>/ :nohlsearch<CR> 由于我的键盘上不方便按F1-12,所以可选择的映射键并不多.
作者回复: 很好的经验分享。👍
2020-08-077 - Ranger:%s/\<\(_*\)\([a-z]\w*\)\ze(/\1\u\2/g 你好,想问一下,\<\(_*\) , 这里的 _ 是换行符的意思吗?
作者回复: 不是,就是处理标识符以“_”开始的情况。
2020-08-142 - Adoy感谢老师用心分享,里面的知识都十分实用!有一个平板的小建议,正则表达式的命令能否用行内代码(markdown里应该是'`' 和 '`' ),看得眼花缭乱哈哈哈
作者回复: 已经用了。极客时间的展示没有背景加灰,有时候不够明显。
2020-08-071 - 阿鸡2. %s!\(\<\|_\)\([a-z]\)!\U\2!g
作者回复: 👍
2022-04-15 - Alvin-L:%s/\<\(_*\)\([a-z]\w*\)\ze(/\1\u\2/g [ 关键是要理解中间这段的意思(从:%s/之后,一直到末尾/g之前), 由于命令没有使用!,所以这条替换命令/是作为功能符使用,/前为模式串,/后是替换串 1,模式串 \<\(_*\)\([a-z]\w*\)\ze( , 2,替换串 \1\u\2 模式串再分成了四段 \< , \(_*\) , \([a-z]\w*\) , /ze( \< 表示一个单词的开头 \(_*\): 分3节,最开头的 \( 与末尾的 \) 表示捕获包起来的内容作为一个分组,并将分组分配为1号,而中间包起来的 _* 表示重复出现任意次(0次1次多次)的下划线_ \([a-z]\w*\) 也分3节, \( 与 \) 捕获分组2号.中间的[a-z]\w* 表示一个小写字母后跟着可重复出现任意次的单词 /ze( 表示模式串匹配的结尾必须紧跟着'('但不包括'(' 替换部分分成两段\1 , \u\2 \1 表示在模式串匹配中捕捉到的1号分组的内容(即0个或多个下划线_) \u\2 表示在模式串匹配中捕捉到的2号分组的内容(即1个小写字符跟着0个或多个标识符),将其第一个字符(即匹配里值得的那个小写字符)变为大写 所以整个意思就是: 匹配到以下划线_开始(或者没有下划线_)第一个字符是小写字符后面跟着任意长度的标识符的字符串(且该字符串紧跟着左圆括号,但不包括左圆括号).然后将第一个小写字符变为大写字符 ]
作者回复: 学习很努力啊。理解正确。 新年快乐!
2021-02-14 - pearl刘东洋两个疑问 1、不过,这样的写法会让像 > 这样的结尾字符在模式中重复出现,因此这并不是最理想的写法——这句没太理解,有同学帮忙举例子解释一下吗? 2、\H 匹配非单词首字符,相当于 ^[A-Za-z_] 这句应该是 \H 匹配非单词首字符,相当于 [^A-Za-z_] 吧
作者回复: 1. 就是指“<[^>]\+>”里把“>”重复了的情况。 2. 嗯嗯,是打字错误。我回头更正一下。谢谢。
2021-01-08 - pyhhou替换那边不是很理解,之前一直以为替换是像下面的格式,匹配的内容和替换的内容中间用空格分开 :%s matchpattern replacepattern 上面 3 个替换的例子,我尝试理解: :%s!\s*//.*$!! ! 可以代替 \, 是不是表示的就是替换后的内容,这里可以理解为直接删除。后面的 \s*//.*$!! 表示的是需要在文本中搜索的内容 :%s!/\*\_.\{-}\*/!!g 按上面的理解方式,第二个例子也是类似的,只不过需要搜索的内容是 /\*\_.\{-}\*/!!,另外最后的 g 表示一行内允许多次搜索 :%s/\<\(_*\)\([a-z]\w*\)\ze(/\1\u\2/g 到这里就不是太理解了,\<\(_*\)\([a-z]\w*\)\ze( 表示的是需要搜索匹配的内容,后面才是需要替换的内容? 感觉主要是 ! 和 / 还有 \ 这三个东西放在一起,看得是真的有点混淆它们具体的意义。还请老师解答一下替换的结构
作者回复: :s 后面的符号是替换的间隔符,但有一定的限制范围。见 :help pattern-delimiter。“:s/搜索/替换/标志”、“:s!搜索!替换!标志”、“:s#搜索#替换#标志”等等都可以的。 对,最后一个替换命令里,\<\(_*\)\([a-z]\w*\)\ze( 是搜索模式,\1\u\2 是替换模式。
2020-08-21 - __@948CSheLL老师您好,我想请问一下【:%s】和【:s】有什么区别?
作者回复: % 代表所有行。也可以用“起始行号,结束行号"的写法。不写,就只替换当前行了。
2020-08-17 - Rock正则表达式有没有什么简单入门的教程
作者回复: 我也和你一样,靠搜索查有哪些教程。先自己看看吧,有没有适合自己的。没免费的好教程的话,可以考虑极客时间的,哈哈。还有,就是直接看文中的例子,通过例子去理解。
2020-08-11