神級編輯器 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

相關文章
相關標籤/搜索