Next: , Previous: , Up: 我想知道多一點   [Contents]


3.7 方便修改的取代

我們常常在寫程式或是文件時打錯字,或是想要修改一些名詞。 這時候要進入插入模式再一一修改很不方便。 而取代在這時會是個不錯的選擇。

首先,最簡單的取代方式是使用按鍵 r ,這是 replace( 取代 ) 的意思。 只要將游標移到想要修改的字元上,按下 r + 想改成的字元即可。 比如說我們想將 tne 的 n 改成 h,先將游標移到 n 上,然後按下 r h ,這樣 tne 就會變成 the 了。 配合 visual 模式,可以將所選的文字都變成同一個字元( 雖然這不太有用就是了 )。 另外 vim 也提供了一個模式專門用來取代文字。 按下 R 便可以進入取代模式,直接輸入文字會將游標的字取代成輸入的字。 基本上就是個不用刪除文字作修改的插入模式。 另外,在插入模式與取代模式按下 INSERT 可以在這兩個模式間作切換。

再來講一個稍微強大一點的取代方式,使用 substitute (取代)命令。 痾,關於 replace 跟 substitute 這兩個英文的差別我不是很清楚。 總之在 vim 中,我們可以用 substitute 做比較複雜的取代。 它的格式是長成這樣子: ‘:[range]substitue/<pattern>/<replace string>/[flag]’ 。 看起來很複雜嗎,我們來慢慢講解。 range (範圍) 跟 flag (標籤) 可以先不用管,那是稍微進階的功能。 所以最基本的格式看成這樣就好了: ‘:substitute/<pattern>/<replace string>/’ 。 ⟨ pattern ⟩ 就是要被取代的文字,可以用正規表示式來描述,這也讓取代變得很強大。 ⟨ replace string ⟩ 是要換成的文字。 比如說,像剛剛講的要將 tne 改成 the,可以輸入 ‘:substitute/tne/the/’ ,然後按下 ENTER 。 覺得輸入 substitute 太長了?可以用縮寫 ‘:s/tne/the/’ 。

在前面介紹正規表示式時,我們有講到 subpattern 的 back reference,這就可以被用在取代上。 利用 ‘\<number>’ ,我們可以描述使用第幾個 subpattern。 比如說原本 pattern 長這樣: ‘abcdefabc’ ,可以利用 subpattern 改成 ‘\(abc\)def\1’ 。 可以比較簡潔的描述。 這在取代時還蠻方便的,有時候我們想取代特定的字,需要用前綴與後綴來限制被取代的字,但這些前綴與後綴又會被取代掉。 比如我們想將 prefix 改成 postfix,而文件裡有 preference 這個字,這是時候就不能直接打 ‘:s/pre/post/’ 。 不然 preference 有可能就變成 postference 了。 利用後綴與 subpattern,我們可以更精確地做取代: ‘:s/pre\(fix\)/post\1/’ 。 如果想要使用 subpattern 但不想被用在 backreference,可以用 ‘\%(’ , ‘\)’ 來包住 subpattern。 比如我們想將 abcabcde 改成 code,但文件裡有 cde,所以需要用後綴與 backreference。 一個寫法是 ‘:s/\(abc\)\{2}\(de\)/co\2/’ ,另一個寫法是 ‘:s/\%(abc\)\{2}\(de)/co\1/’ 。 第二種寫法可以區分要或不要用在 back reference 的 subpattern,如果寫的正規表示式比較複雜時會比較容易用。 雖說這個情況本身就不太會遇到就是了。

在預設的情況下,substitute 只會取代游標所在那行第一個符合 pattern 的文字。 所以如果要將 pre pre 改成 post post,用 ‘:s/pre/post/’ 我們只能得到 post pre。 這時候就需要用 range 與 flag 了。 首先講 flag,我只講我會的兩個,其他還請自行 :help s_flags 。 第一格是最常用的 g flag,我是以 global (全域) 來記它的。 這就是上面例子的解答,使用 g flag,vim 會取代該行所有符合 pattern 的文字。 所以 ‘:s/pre/post/g’ 就可以將 pre pre 改成 post post 了。 另一個我覺得不錯用的是 n flag,這是 number (次數) 的意思。 它不會取代文字,而是會顯示找到的 pattern 有幾個,這讓我們可以計算文件中 pattern 出現的次數。 想我之前還用這個方式來算課程作業中 clause 跟 literal 有幾個呢。 離題了,這兩個就是我所知的 substitute flag,基本上也算夠用了。

接著講講 range,range 的概念也可以用在其他命令上,只要有支援。 這有點像運算子,只要學一次,就可以套用到很多地方。 題外話,每個運算子都有對應的命令,方便用來寫 script。 如果沒寫 range,預設是游標所在那行,也可以顯式的寫 ‘.’ ,這是游標所在那行的意思。 range 的格式就像 ‘\{n,m\}’ 一樣,用 ‘,’ 來取分起始。 所以我們可以用 ‘:1,5s/pre/post/g’ 來將 1 到 5 行所有出現的 pre 改成 post。 特殊符號 ‘$’ 表示最後一行,所以 ‘:1,$s/pre/post/g’ 表示將整個文件的 pre 改成 post。 也可以用簡寫 ‘%’ 來表示 ‘1,$’ 。 另外可以用相對行號,比如 ‘:.-1,.+5s/pre/post/g’ 表示將前一行到下五行內的所有 pre 改成 post。 比較常用的應該還是 ‘%’ ,其他就看個人喜好了。 配合 visual 模式,可以只取代所選的範圍內的字。 在選取文字後按下按下 : 進入命令模式,螢幕最下方會顯示 ‘:'<.'>’ 。 ‘'<’, ‘'>’ 表示被選取的兩端。

關於取代大約就這樣,還請各位自行玩玩看,找出自己喜歡的取代方式。


Next: , Previous: , Up: 我想知道多一點   [Contents]