Vim案例兩則


在博問中看見兩個比較典型的Vim處理文本的案例,總結一下,希望對大家有所幫助。如果大家有好的方法,歡迎討論。尤其是第二個案例,如果能夠一個命令處理更好。

案例一

這是在博問中看到的一個問題,原始文本如下。

要求處理成下面的樣子,也就是把逗號從行尾移動到下一行第一個單詞前面。

我的第一想法是先將2-6行的逗號刪除,然后在3-7行加上逗號即可。

刪除2-6行的逗號

:%s/,// 

解釋一下:

  • : 冒號在Vim里面是命令引導符,想要輸入命令必須先輸入冒號。
  • % 表示匹配所有行
  • s/old/new/ 表示用new來替換old。s表示substitude(替換)。在s/,//中,old是逗號,new是空(注意后面兩個斜線之間啥也沒有,表示空)。

在3-7行前面加上逗號

:3,7s/\</,/

解釋一下:

  • 3, 7 表示對第3行至第七行進行處理,在Vim中m, n表示對第m到第n行進行處理,比如:1,10d表示刪除1-10行
  • s/\</,/ 表示用逗號替換\<,<表示單詞邊界,屬於特殊字符,需要轉義,所以是\<

這樣就搞定了,但是轉頭一想,有沒有更簡單的辦法呢?上面的辦法雖然也很簡單,但是需要兩次命令才能完成,有沒有辦法用一個命令搞定呢。搞了一會,終於搞定,命令如下。

:%s/,\n\(\s*\)/\r\1,/

解釋一下:

  • %s/old/new/ 表示對所有行中的old用new來替換,這里每一行只有一個逗號,所以不用加g,如果有多個逗號,那么要變成%s/old/new/g的形式,g表示對每行中的所有滿足條件的文本進行替換。也就是說%是縱向的,而g是橫向的。
  • ,\n\(\s*\) 匹配逗號,換行以及行首的若干空格。如下圖                                                     
  • \r\1,匹配換行,行首的若干空格及逗號,這里\1是回溯引用,表示前面第一個括號對應的匹配,也就是行首的若干空格,因為添加逗號時不能破壞這些空格,所以匹配的時候進行保留以便替換時引用之。

注意,上面的(和)屬於特殊字符,需要轉義,如果覺得\(\)這種方式難看,可以在表達式前面加上\v。如此則特殊字符無需再轉義,可以像perl一樣使用正則表達式了。

:%s/\v,\n(\s*)/\r\1,/g

案例二

也來來自於博問,要求將只包含5個字符(字母,數字,或者下划線)的行,刪除其行尾的換行符。

原始文本如下:

處理之后如下:可見2,3,4行的換行符都被刪除了。

我首先想到的命令是

:g/\v^\w{5}$/ s/\n//g

解釋一下:

整個表達式可以分成兩個主要部分。:g/\v^\w{5}$/設為A,s/\n//g設為B。那么這個命令的含義就是對於滿足條件A的行,執行命令B。也就是對於所有只包含5個字符的行,刪除其行尾的換行符。

  • :g/patter/ g表示global,patter是一個正則表達式,這句話的意思是對於所有滿足patter的行,用隨后地命令(即s/\n//g)進行處理。
  • \v^\w{5}$ 表示只包含5個字符的行,\v表示后面的特殊字符不用轉義,比如{}。^表示行首,$表示行尾。\w表示單詞字符,即字母,數字或者下划線。
  • s/\n//g 表示用空替換\n,也就是刪除換行符。

但是非常遺憾的是,執行完這個命令后,結果並不正確,如下:

可以看到,第二個abcde末尾的換行並沒有刪除掉,為什么會這樣呢?仔細分析一下這個命令的執行步驟。

首先Vim解析命令然后找到第一個滿足條件的行abcde,並刪除其末尾的換行符,此時文本變成下面的樣子。

這時,第二行文本是abcdeabcde,共10個字符,已經不再滿足5個字符的條件了,所以Vim不會再刪除其末尾的換行了,因而就產生了上面的錯誤結果。

看來用一個命令處理有點困難,那就分成兩個吧。雖然麻煩一點,但是結果正確。

首先把要處理的行加上一個特殊標志,這個標志能夠將待處理的行與其它行區別開來,所以要選擇未在文本中出現的字符。另外一個要求是處理完之后這個標志也要刪除,所以把它加在行尾,可以與換行符一並刪除。

先在包含5個字符的行末尾加上#

:%s/\v(^\w{5}$)/\1#/g

刪除所有的#和換行符。

:%s/#\n//g

由於這次不再以字符個數來甄別處理的行,而是以#號來定位,即使兩行合並之后,#號仍然存在,結果自然就正確了。你有更簡單的辦法么?

參考

關於跨行匹配,下面這個網頁上有詳細的介紹。

Vim, Search across multiplelines


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM