神级编辑器 Vim 使用-正则替换篇

Vim 的替换查找是其核心功能, 功能极其强大, 经过其规则匹配, 能够很快速地完成咱们不少须要大量人力操做的工做, 并且可对多文件使用查找/替换功能.html

himg

本系列教程共分为如下五个部分:正则表达式

  1. 神级编辑器 Vim 使用-基础篇
  2. 神级编辑器 Vim 使用-操做篇
  3. 神级编辑器 Vim 使用-插件篇
  4. 神级编辑器 Vim 使用-正则操做篇
  5. 神级编辑器 Vim 使用-最后

正则匹配的模式

编程界实现了多种正则匹配引擎, vim 的正则匹配引擎是独有的, 其风格相似于 POSIX, 可是咱们可经过将其匹配模式设为:编程

  • \v: (very magic) 来开启 Perl 模式, 此模式下( 已经被转义, 若是要搜索 (, 必须转回原义, \(
  • \V: (very nomagic) 来开启开启原义模式, 此模式下直接搜索( 便可搜索到 (
  • \m: 默认模式, 不指定任何模式时使用的就是此模式. 此模式下仅部分字符有特殊含义, ( 没有被转义, 仍然可经过 ( 搜索到 (
  • \M: (nomagic) 其功能相似于 \V 原义开关, 不一样的是, 一些字符会自动具备特殊含义, 即符号 ^$

本文只讨论默认模式下(\m 模式)下的正则匹配, 其余模式下的原理相似, 读者可自行研究vim

查找

查找元字符

元字符是正则匹配的一个概念, 经过元字符能够快速找出目标字段.markdown

  • .: 表示匹配任意 一个 字符. 例: c..l 表示任意以 c 开头, 中间有两个任意字符, l 结尾的字段.
  • .*: 表示匹配 任意多个 字符. 例: c.*l 表示任意以 c 开头 l 结尾的字段(不会将一个字段进行跨行处理, 所以很是智能, 很频繁使用)
  • $: 匹配行尾. 例: /d.*$ 表示匹配到以 d 开头到行尾中的全部内容, /123$ 表示以 123 结尾的全部字段
  • ^: 匹配行首. 例: ^.*d 表示匹配到行首到 d 的全部内容, /^123 表示以 123 开头的字段
  • \< : 匹配单词词首
  • \>: 匹配单词词尾. 例: /\<f\> 表示只匹配 f 单词, 若是其前有任何字符它就不是单词, 不会被匹配到.
  • *: 表示其前字符能够重复 0~无数 次. 如 /be* 会匹配到 b, be, bee ..., 由于 e 重复零次就是没有, 因此会返回 b, 贪婪匹配模式, greedy
  • \+: 表示其前字符必须重复 1~无数 次, 如 /be\+ 会匹配到 be, bee, beee ..., 贪婪匹配模式
  • \(-): 0 或多个, 非贪婪匹配模式, non-greedy, 与 * 相对
  • \?\=: 表明其前字符必须重复 0 或者 1 次.
  • \{n,m} : 其前字符必须重复 n 到 m 次, 贪婪匹配模式
  • \{-n,m} : 其前字符必须重复 n 到 m 次, 非贪婪匹配模式
  • [adz]: 匹配 a, d, z 中的任意 一个, 括号内也但是数字, 如 [2-5] 表示匹配 2, 3, 4, 5 中的任意一个数字
  • \|; 或的意思, 表示只要符合其前或其后任意一个字符便可. 例: /one\|two\|three 表示匹配 one, two, three 中的任意一个. end\(if\|while\|for\) 表示会查找到 endif, endwhile, endfor 中的任意一个.
  • [^a]: 匹配除 a 之外的任意 字符
  • [a-c]: 匹配 a, b, c 中的任意一个, 递增的顺序
  • \d: 匹配十进制数字中的任意一个, 等同于 [0-9]. 例: /\d\d:\d\d:\d\d 表示查找如 17:31:00 格式的字符
  • \D: 匹配除十进制数字外的任意一个字符, 等同于 [^0-9]
  • \x: 匹配十六进制数字中的任意一个, 等同于 [0-9A-Fa-f]
  • \X: 匹配除十六进制数字外的任意一个字符, 等同于 [^0-9A-Fa-f]
  • \w: 匹配一个单词(对中文来讲很是鸡肋, 由于只有 Vim 断定是单词的才会进行匹配, 与normal 模式下的 w, b, e 匹配规则相同)
  • \W: 匹配除单词外的全部字符. 由于在 vim 中中文所有不被认为是单词, 所以, 此匹配会选中全部中文字段.
  • \t: 表明 tab , 可以使用此方法将全部 tab 替换为空格
  • \s: 配空白字段, 包含 tab 与空格, 在 pattern 中使用此查找空白, 在 string 中就能够直接使用空格或者 tab 来输入以替换了
  • \S: 匹配非空白字段, 等同于 [^\s]
  • \n: 匹配换行符
  • \_s: 匹配换行或空白
  • \_a: 匹配换行或单词(由于是单词, vim 不会匹配中文)
  • \C: 区分大小写地查找或替换, 例: /\CText 表示只会查找Text, 不会查找 texttExt
  • \c: 不区分大小写地查找替换(已经在 vim 中设置了默认不区分了)

如上所述, ., *, [, ], ^, %, /, ?, ~, $ 这十个字符有特殊含义, 若是对这十个字符进行匹配, 须要添加 \编辑器

查找时的经常使用操做

  • :noh : 取消查找模式的高亮匹配
  • *: 全文查找当前光标处单词 (n 为向下方向)
  • #: 全文查找当前光标处单词 (n 为向上方向)
  • n: 下一个列出的关键字
  • N: 上一个列出的关键字
  • gn: 进入面向字符的可视模式, 并选中下一项匹配
  • gN: 进入面向字符的可视模式, 并选中上一项匹配
  • gUgn: 使下一处匹配改成大写
  • <C-r><C-w>: 根据当前查找模式下已经输入的内容结合全文进行自动补全
  • /<UP>: 直接调用上次的查找逻辑.
  • /<DOWN>: 直接调用下次的查找逻辑.
  • /<C-N>: 直接调用下次的查找逻辑.
  • /<C-P>: 直接调用上次的查找逻辑.
  • /<C-r>/: 使用寄存器 / 将上次查找的值直接插入到当前模式中来

查找逻辑

/pattern/[e]oop

查找实例

  • /view: 全文查找 view 关键字 (n 为向下方向)
  • ?view: 全文查找 view 关键字 (n 为向上方向)
  • /\cview: 全文查找 view 关键字(大小写不敏感)
  • /view/e: 默认的查找会将光标置于单词首部, 使用 e 保证光标位于尾部, 方便 . 命令的调用
  • //e: 匹配 pattern 为空则直接重用上次的逻辑进行查找
  • /\<f\>: 使用 <> 限定词首与词尾, 保证只查找单词 f
  • /^\n\{3}: 查找三个空行

还有一种是使用 global 命令: :g/pattern/d , 含义是对 patter 进行匹配搜索, 而后执行命令 delete, 也是基于查找的ui

替换

替换元字符

  • \r: 换行, 在 pattern 中使用\n 做为搜索串, 在string 中使用\r 做为换行命令(若是在 string 中仍然使用 \n 的话会出错)
  • \u\l: 把替换串中的下一个字符分别变成大写或者小写.
  • ~: 用在替换串中, 表明使用上次的替换串.
  • &: 用在替换串, 它表明与搜索模式想匹配的整个文本, 即“重现”搜索串. 这在试图避免重复输入文本时颇有用.
  • \U\L: 将跟在后面的匹配串所有变成大写或小写

替换逻辑

[range]s/pattern/string/[c,e,g,i]spa

  • range: 范围, 1,7 指第一行至第七行. 也可使用 % 表明当前的文章(也能够理解为所有的行), # 表明前一次编辑的文章(基本不用)
  • s : 表明当前的模式为替换
  • /: 做为分隔符, 若是确实要替换文中的 /, 那么可使用 # 代替做为分隔符. 例如 :s#vi/#vim#g, 表明替换 vi/vim
  • pattern : 要被替换掉的字符
  • string : 将要使用的字符
  • c : confirm, 每次替换前会询问
  • e: ignore, 忽略错误(默认找不到会提示 pattern not found, 可是若是设置 vim 设置批量替换命令的话某一个项未匹配到不能影响到下一项的执行, 可使用此关键字, :silent %s/x/y/g == :%s/x/y/ge )
  • g : global, 整行替换(基本上是必加的, 不然只会替换每一行的第一个符合字符)
  • i : ignore, 不区分大小写
  • I: 区分大小写

变量替换

在表达式中可使用 \(\) 将表达式括起来, 而后既可在后面使用 \1 \2 来依次访问由 \(\) 包围起来的内容.插件

例: :s/\(\w\+\)\s\+\(\w\+\)/\2\t\1 表示将 data1 data2 修改成 data2 data1

替换实例

  • r : 进入单字符替换模式
  • R : 进入替换模式
  • &: 重复上次的替换过程
  • :s/vi/vim/ : 只替换当前行的第一个 vi 为 vim
  • :s/vi/vim/g : 替换当前行的全部 vi 为 vim
  • :%s/vi/vim/g : 替换全文全部 vi 为 vim
  • :%s/vi/vim/gi : 替换全文全部 vi 为 vim, 大小写不敏感
  • :n,$s/vi/vim/gci : 替换从第 n 行到结尾全部 vi 为 vim, 每次替换提示, 不区分大小写
  • :.,$s/vi/vim/gci : 替换从当前行到结尾全部 vi 为 vim, 每次替换提示, 不区分大小写
  • :.,+3s/^/#: 在当前行到下面三行添加 # 的注释
  • :g/^\s*$/d : 删除全部空行
  • :215,237 s/\(.\)$/\1(自定义)/c: 将 215 至 237 行尾部添加 (自定义)
  • :%s/^\n$//gc/ : 替换多个空行为一个空行
  • :122,250s/\(201\d*\)\.\(\d*\)\.\(\d*\)\s/\1-\2-\3_/gc: 替换 2017.12.31类型的字段为2017-12-31_
  • %s/\(\](http:.*com\/\)\(HK.*\))/\](https:\/\/a.hanleylee.com\/\2?x-oss-process=style\/WaMa)/gc: 将[](http: ....com) 替换成 https 而且尾部带有样式参数
  • :%s/\(a.*bc\)\(<.*>\)\(xy.*z\)/\3\2\1/gc: 使用缓冲块实现对先后区域匹配并翻转位置(须要时再理解)
  • :%s/hello/&, world/: 将会把hello替换成hello, wolrd
  • :%s/.*/(&)/: 将会把全部行用()包含起来
  • : s/world/\U&/: 把 world 变成 WORLD
  • :%s ; /user1/tim;/home/time;g: /user1/tim改成/home/time, 除了/字符外, 还可使用除反斜杆, 双引号和竖直线 \, ", 和 |, 以外的任何非字母表, 非空白字符做为分隔符, 在对路径名进行修改时, 这点尤为便利
  • :s: 与 :s//~/相同, 重复上次替换
  • :&: 重复上次替换
  • %s/\<child\>/children/g: 保证在 child 是个完整单词的状况下进行替换
  • :g/mg[ira]box/s/box/square/g: 将 mgibox routine, mgrbox routine, mgabox routine, 中的 box 换为 square
  • &: 直接使用 & 也是重复上次替换的意思

替换时系统会对用户进行询问, 有 (y/n/a/q/1/^E/^Y)

  • y : 表示赞成当前替换
  • n : 表示不一样意当前 替换
  • a : 表示替换当前和后面的而且再也不确认
  • q : 表示当即结束替换操做
  • 1 : 表示把当前的替换后结束替换操做;
  • ^E : 向上滚屏
  • ^Y : 向下滚屏,

多文件查找与替换

多文件操做的基础是必定要 设置好工做目录, 由于添加文件到操做列表是以当前路径下的文件进行判断筛选的, 设置当前路径可以使用如下方式:

  • 手动 :cd path
  • NERDTree 插件的 cd 命令
  • netrw 插件的 cd 命令
  • .vimrc 中设置 set autochair 自动切换当前工做路径

多文件查找

himg

逻辑

vimgrep /pattern/[g][j] <range>

  • vimgrep: 批量查找命令, 其后可直接加 ! 表明强制执行. 也可使用lvimgrep , 结果显示在 list 中
  • patten: 须要查找的内容, 支持正则表达式, 高级用法见元字符
  • g: 若是一行中有多个匹配是否所有列出
  • j: 搜索完后直接定位到第一个匹配位置
  • range : 搜索的文件范围
    • %: 在当前文件中查找
    • **/*.md: 在当前目录即子目录下的全部 .md 文件中
    • *: 当前目录下查找全部(不涉及子目录)
    • ** : 当前目录及子目录下全部
    • *.md : 当前目录下全部.md 文件
    • **/* : 只查找子目录

查找的结果使用 quick-fix 来进行展现, 可以使用 :copen 查看全部结果项并进行相应跳转, 具体操做参考 神级编辑器 Vim 使用-操做篇

实例

  • :vimgrep /hello/g **: 在当前目录及子目录下的全部文件内查找 hello 字符串

quickfix-list 与 location-list 的区别

quickfix-list 是一个完整的窗口, 能够移动上下光标, 按下 enter 进行打开文件

location-list 只是一个局部的显示区域, 只能简单显示查找结果的信息, 目前看来没有必要使用此选项

多文件替换

多文件替换所依赖的是 vim 中的参数列表概念, 这里仅对流程命令进行演示, 具体的参数列表操做参考 神级编辑器 Vim 使用-操做篇

  • args: 显示当前的全部参数列表
  • :args *.md aa/**/*.md 表示添加子文件夹下的 md 文件及 aa 文件夹下的和其子文件夹下的 md 文件到参数列表中
  • :argdo %s/oldword/newword/egc | update : 对全部存在参数列表中的文件执行命令, s 表明替换, % 指对全部行进行匹配, g 表明整行替换(必用), e 指使用正则表达式, c 表明每次替换前都会进行确认, update 表示对文件进行读写
  • :argdo %s/!\[.*\]/!\[img\]/gc: 将全部参数列表中的以 ![ 开头, 以 ] 结尾的全部字段改成 [img]
  • :argdo write: 将全部参数列表中的内容进行缓冲区保存

最后

本文做者 Hanley Lee, 首发于 闪耀旅途, 若是对本文比较承认, 欢迎 Follow

相关文章
相关标签/搜索