vim從入門到精通

harriszh發表於2022-05-24

安裝

下載windows安裝包, 最新版在這裡
下載中文幫助安裝包, 最新版在這裡
安裝vim-plug外掛, 原檔案在這裡, 下載plug.vim,然後把它放到vim安裝路徑的autoload目錄下

VIM簡介

VIM是一種信仰。

對我來說vi是禪, 使用vi就是使用禪。每個命令都是心印,這對使用者來說是深奧的,對未入門者來說是無法瞭解的。每次使用它你都能發現真理。 --Satish Reddy

商業化產品可能是有用的, 但最好的東西往往是免費的, 空氣, 水, vim

高效編輯的原則

形成過程

  • 自省, 找出重複/低效的部分
  • 尋找solution
  • 使之成為習慣
  • 7 Habits

    • 他們能做事主動。 (“積極主動”)
    • 他們能關注目標。 (“以終為始”)
    • 他們能確定要務。 (“要事第一”)
    • 他們能與人共贏。 (“雙贏思維”)
    • 他們能與人溝通交流。 (“知彼解己”)
    • 他們能與人合作。 (“統合綜效”)
    • 他們能反省自己並彌補不足。 (“自我更新”)

區分學習和使用

  • 學習是投入,使用是產出
  • 學習是投資,使用是收益
  • 不要第二次尋找同一問題的解決方案(DRY)

拿來主義

  • 選擇性收集技巧, 有用的 VS 對你有用的
  • 避免收集對自己無用的高度特殊化的技巧
  • 不要為用不到的功能買單

    • 不要提前買單
    • 技能的投入產出比
    • 遺忘曲線
    • 打磨技藝持續前進

不斷提高

  • 理解而非記憶
  • 培植而非收藏
  • 精心經營個人化功能子集
  • 全面瞭解,不要淺嘗輒止

態度

  • 學而不用,積而不發
  • 瞭解工具實際被設計能做的事, 而不是你希望它能做的事.
  • 高效與否, 操之在你

    • 工具只會跟使用者一樣好
  • 開放態度, 不要拒絕其它工具

    • 手持錘子,滿世界都是釘子

第一課

學會自己搜尋答案

圖片.png

第二課

完成vimtutor

vimtutor位於vim安裝目錄裡,一個可執行程式(指令碼)
它大約需要20分鐘

第三課 Motion

通用

  • h/l/k/j
  • G/{num}G/gg/:{num}
  • %
  • gk/gj
  • 0/^/$
  • f{char}/F{char}/t{char}/T{char}/;/, : t=till=find-1
  • -/+/_

練習

To err is human.  To really foul up you need a computer. 
           <------------  ------------->
                    Th     tn

單詞級移動

keyaction
wW移動到下一單詞的開頭
bB移動到上一單詞的開頭
eE移動到游標所在單詞的末尾
       ge      b        w                               e
       <-     <-        --->                           --->
This is-a line, with special/separated/words (and some more).
   <----- <-----       -------------------->          ----->
     gE      B                   W                       E
        ge      b          w                            e

大範圍移動

keyaction
%移動游標到括號左半部分( 包括(、{、[ )對應右半匹配部分( )、}、] )
}移動游標到當前段落的末尾
{移到游標到當前段落的開頭
H移動游標到螢幕的第一行
M移動游標到螢幕的中間一行
L移動游標到螢幕的最後一行
Ctrl + f向前滾動一頁
Ctrl + b向後滾動一頁
Ctrl + u向前滾動半頁
Ctrl + d向後滾動半頁
/<string>向前查詢, 結合n/N可以重複向前向後查詢同一字元
?<string>向後查詢, 可以結合n/N

關於查詢

  • .*[]^%/\?~$有特殊含義,如果要查詢它們,在在前面加上\.
  • 可以用:set ic:set noic來忽略或不忽略大小寫
  • 輸入/?後可以用<Up>或<Down>來查詢歷史記錄。
  • 可以在單詞上用*#來向前或向後查詢游標下單詞
  • 如果要精確匹配, 用\<\>來精確匹配開頭或結尾,兩者可以同時使用,如/\<the\>,這樣three不會被匹配

位置標記

keydesciption
m{a-zA-Z}把位置標記 {a-zA-Z} 設在當前游標位置 (不移動游標,這不是動作命令)。
g'{mark}跳轉到指定的位置標記 {mark},但在當前緩衝區內跳轉時,不改變跳轉表。
:marks列出所有的位置標記 (這不是動作命令),第一列的編號為零。

標誌說明

markdescription
'a - 'z小寫位置標記,在每個檔案內有效。
'A - 'Z大寫位置標記,也叫做檔案標記,在檔案間都有效。
'0 - '9數字位置標記,在 .viminfo 檔案裡設定。

跳轉

keyaction
CTRL-O轉到跳轉表裡第 [count] 個較舊的游標位置 (不是動作命令)。
CTRL-I轉到跳轉表裡第 [count] 個較新的游標位置 (不是動作命令)。
:ju[mps]打出跳轉表 (不是動作命令)。
:cle[arjumps]清除當前視窗的跳轉表。

編輯命令

<number> <operator> <text object or motion>
<次數> <操作符> <文字物件或移動命令>

操作符

keyaction
c修改 (change)
d刪除 (delete)
y抽出 (yank) 到暫存器 (不改變文字)
~變換大小寫 (只有當 'tildeop' 置位時有效)
g~變換大小寫
gu變為小寫
gU變為大寫
!通過外部程式過濾
=通過 'equalprg' (若為空,C-indenting) 過濾
gq文字排版
gw文字排版,不移動游標
>右移
<左移
zf定義摺疊

高階技巧: 可以用":"命令定義一個動作, 例如d:call search("f")<CR>, 如果該命令多於一行,則不能用"."重複。

物件導向型別

一共三種: 字元/行/列

keytype
v在操作符後和動作命令之前應用: 即使該動作是面向行的,也強制該操作面向字元。
V在操作符後和動作命令之前應用: 即使該動作是面向字元的,也強制該操作面向行。
CTRL-V在操作符後和動作命令之前應用: 強制該動作面向列塊。

練習: dj, dvj, d<C-V>j

物件定義

  • word: 一個單詞由字元、數字和下劃線序列或者其他的非空白字元的序列組成。單詞間可以空白
    字元 (空格、製表、換行) 分隔。這一規則可以用 'iskeyword' 選項改變。空行也被認
    作單詞。
  • WORD: 一個字串由非空白字元序列組成。字串以空白分隔。空行也被認作字串。
  • sentence: 一個句子以 '.'、'!' 或者 '?' 結尾並緊隨著一個換行符、空格或者製表符。標點和空
    白字元之間可以出現任何數量的閉括號和引號: ')'、']'、'"' 和 '''。另,段落和小節
    的邊界也視為句子的邊界。
  • paragraph: 一個段落從空行或某一個段落巨集命令開始,段落巨集由 'paragraphs' 選項裡成對出現的字
    符所定義。它的預設值為 "IPLPPPQPP TPHPLIPpLpItpplpipbp",也就是巨集 ".IP"、".LP"
    等 (這些是 nroff 巨集,所以句號一定要出現在第一列)。小節邊界也被視為段落邊界。
    注意 空白行 (只包含空白) 不是 段落邊界。
  • section: 一個小節從首列出現的換頁符 (<C-L>) 或某一個小節巨集命令開始。小節巨集由 'sections'
    選項裡成對出現的字元所定義。它的預設值是 "SHNHH HUnhsh",也就是說小節可以從如
    下的 nroff 巨集開始: ".SH"、".NH"、".H"、".HU"、".nh" 和 ".sh"。

文字物件

keydescription
aw"一個單詞",選擇 [count] 個單詞 (見word)。包括開頭或拖尾的空白,但不單獨計算。在可視面向行的模式下,"aw" 切換到可視面向字元的模式。
iw"內含單詞",選擇 [count] 個單詞 (見word)。單詞之間的空白也被算為一個單詞。在可視面向行的模式下,"iw" 切換到可視面向字元的模式。
aW"一個字串",選擇 [count] 個字串 (見WORD)。包括開頭或拖尾的空白,但不單獨計算。在可視面向行的模式下,"aW" 切換到可視面向字元的模式。
iW"內含字串",選擇 [count] 個字串 (見WORD)。字串之間的空白也被算為一個字串。在可視面向行的模式下,"iW" 切換到可視面向字元的模式。
as"一個句子",選擇 [count] 個句子 (見sentence)。可視模式下它切換為面向字元的模式。
is"內含句子",選擇 [count] 個句子 (見sentence)。可視模式下它切換為面向字元的模式。
ap"一個段落",選擇 [count] 個段落 (見paragraph)。特例: 空白行 (只包含空白的行) 也被視為段落邊界。可視模式下它切換為面向行的模式。
ip"內含段落",選擇 [count] 個段落 (見paragraph)。特例: 空白行 (只包含空白的行) 也被視為段落邊界。可視模式下它切換為面向行的模式。
a(ab"一個()塊",包括'(' 和 ')'
i(ib"一個()塊",不包括'(' 和 ')'
a{a{"一個{}塊",包括'{' 和 '}'
i{i{"一個{}塊",不包括'{' 和 '}'
a"a'a\`"一個引號字串", 包括引號
i"i'i\`"一個引號字串", 不包括引號

常見命令

keyactions
x刪除游標下的字元 ("dl" 的縮寫)
X刪除游標前的字元 ("dh" 的縮寫)
D從當前位置刪除到行尾 ("d$" 的縮寫)
dw從當前位置刪除到下一個單詞開頭
db從當前位置刪除到前一個單詞的開頭
diw刪除游標上的單詞 (不包括空白字元)
daw刪除游標上的單詞 (包括空白字元)
dG刪除到檔案末
dgg刪除到檔案首

上面的d可以改成c或y

插入和替換

插入模式命令

keyaction
a在游標後附加文字 [count] 次。如果游標在空行的第一列,啟動插入模式。但在置位了 'virtualedit' 以後就不是!
A在行尾附加文字 [count] 次。
i在游標前插入文字 [count] 次。在插入模式裡使用 CTRL-O 的時候,i_CTRL-O 不支援計數。
I在本行第一個非空白字元之前插入文字 [count] 次。如果 'cpoptions' 裡有 'H' 標誌位而本行只有空白,在最後一個空白前插入。
gI在第一列插入文字 [count] 次。
gi在當前緩衝區最近一次插入模式停止的位置繼續插入文字。該位置記在 '^ 位置標記裡。如果標記在行末之後,和 "^i" 有所差異。該位置在插入/刪除行時會自動修正。但_不_在插入/刪除字元時被修正。使用 :keepjumps 命令修飾符時,不改變 '^` 位置標記。
o在游標下方開啟新行,並插入文字,重複 [count] 次。如果 'cpoptions' 裡有 '#' 標誌位,忽略計數。
O在游標上方開啟新行,並插入文字,重複 [count] 次。如果 'cpoptions' 裡有 '#' 標誌位,忽略計數。

用<Esc>或<Ctrl-C>退出插入模式

Ex插入命令

keyActions
:{range}a[ppend][!]在指定行下方新增若干行。如果沒有給出 {range},文字會在當前行之後插入。加入 [!] 切換此命令執行時的 'autoindent'。
:{range}i[nsert][!]在指定行上方新增若干行。如果沒有給出 {range},文字會在當前行之前插入。加入 [!] 切換此命令執行時的 'autoindent'。

這兩個命令會繼續要求行,直到你輸入了只包含 "." 的一行。小心反斜槓開始的行,見 line-continuation

Ex 模式 (見 -e) 下,行尾的反斜槓可用來插入 NUL 字元。所以要使一行以反斜槓結尾,用兩個反斜槓。也就是說僅在行尾情況下,反斜槓數目減半。

注意: 這些命令不能和 :global:vglobal 一起使用。":append" 和 ":insert" 在 ":if" 和 ":endif"、":for" 和 ":endfor" 還有 ":while" 和 ":endwhile" 之間不能很好的工作。

插入檔案

keyaction
:r[ead] [++opt] [name]在游標下方插入檔案 [name] (預設: 當前檔案)。
:{range}r[ead] [++opt] [name]在指定行下方插入檔案 [name] (預設: 當前檔案)。
:[range]r[ead] [++opt] !{cmd}執行 {cmd} 並把它的標準輸出插入到游標下方。臨時檔案會建立來儲存命令輸出的結果,並被讀到緩衝區裡。'shellredir' 用來儲存命令的輸出結果,它可以設定是否包含標準錯誤的輸出。

插入模式下的一些快捷鍵

keyaction
<Esc>CTRL-[結束插入或替換模式,回到普通模式。結束縮寫。
CTRL-C退出插入模式,回到普通模式。不檢查縮寫。不啟用 InsertLeave 自動命令事件。
CTRL-@插入最近插入的文字,並停止插入。
CTRL-A插入最近插入的文字。
<BS>CTRL-H刪除游標前的字元 。
<Del>刪除游標下的字元。如果游標在行尾,並且 'backspace' 選項包括 "eol",刪除 <EOL>;下一行就此附加於當前行之後。如果你的 <Del> 鍵不正確,見 :fixdel。
CTRL-W刪除游標前的單詞
CTRL-U刪除當前行上游標前的所有輸入字元。
<Tab>CTRL-I插入製表。如果開啟 'expandtab' 選項,等價數目的空格被插入 也可使用 CTRL-Q <Tab>
<NL>CTRL-J開始新行。
<CR>CTRL-M開始新行。
CTRL-K {char1} [char2]輸入二合字母 (見digraphs)。當 {char1} 為特殊字元時,該鍵的鍵碼以 <> 形式插入。例如字串 <S-Space> 可以這樣輸入: <C-K><S-Space> (兩個鍵)。兩個鍵都不考慮對映。
CTRL-N查詢下一個關鍵字 (見 i_CTRL-N)。
CTRL-P查詢上一個關鍵字 (見 i_CTRL-P)。
CTRL-T在當前行開始處插入一個 shiftwidth 的縮排。縮排總是取整到 'shiftwidth' 的倍數 (這是 vi 相容的)。
CTRL-D在當前行開始處刪除一個 shiftwidth 的縮排。縮排總是取整到 'shiftwidth' 的倍數 (這是 vi 相容的)。
0 CTRL-D刪除所有當前行的縮排。
^ CTRL-D刪除當前行的所有縮排。縮排在下一行上恢復。這可以用於插入卷標。
CTRL-V如果下一個是非數字,按本義插入。對特殊鍵而言,插入其終端程式碼。CTRL-V 之後緊接著輸入的字元不經過對映。注意: 當 CTRL-V 被對映時 (例如,用來貼上文字),你可能經常需要使用 CTRL-Q 來代替
CTRL-SHIFT-V與 CTRL-V 類似,除非啟用了 modifyOtherKeys,此時插入帶修飾符的鍵的轉義序列。
CTRL-Q等同於 CTRL-V。
CTRL-X進入 CTRL-X 模式,一個子模式。那裡你可以給出命令來補全單詞或者滾動視窗。見 i_CTRL-Xins-completion
CTRL-E插入游標下面的字元。
CTRL-Y插入游標上面的字元。注意 CTRL-E 和 CTRL-Y 不使用 'textwidth',從而可以從長行裡複製字元。
CTRL-]切換縮寫,不插入字元。
<Insert>切換插入和替換模式。

插入暫存器內容

CTRL-R {register} 用於插入暫存器內容,在輸入CTRL-R之後會有"顯示出來,這時你需要輸入暫存器名字

registerUsage
"無名暫存器,包含最近刪除或抽出的文字
%當前檔名
#輪換檔名
*剪貼簿內容 (X11: 主選擇)
+剪貼簿內容
/最近的搜尋模式
:最近的命令列
.最近插入的文字
-最近的行內 (少於一行) 刪除
=表示式暫存器;你會被提示輸入一個表示式 (見expression)

CTRL-R {register}還有幾個變種:

  • CTRL-R CTRL-R {register} : 文字按本義插入,這意味著如果暫存器包含 <BS> 這樣的字元,結果會不同。例如,如果暫存器包含 "ab^Hc": CTRL-R a 產生 "ac"。CTRL-R CTRL-R a產生 "ab^Hc"。
  • CTRL-R CTRL-O {register} : 按本義插入暫存器內容,並且不進行自動縮排。
  • CTRL-R CTRL-P {register} : 按本義插入暫存器內容,修正縮排

複製並移動

keysUsage
"{a-zA-Z0-9.%#:-"}指定下次的刪除、抽出和放置命令使用的暫存器 {a-zA-Z0-9.%#:-"} (大寫字元使得刪除和抽出命令附加到該暫存器) ({.%#:} 只能用於放置命令)。
["x]y{motion}抽出 {motion} 跨越的文字 [到暫存器 x]。如果沒有字元被抽出 (例如,在第一列執行 "y0") 並且 'cpoptions' 裡包括 'E' 標誌位,這是一個錯誤。
["x]yy抽出 [count] 行 [到暫存器 x]linewise行動作。
["x]Y抽出 [count] 行 [到暫存器 x] (等同於 yy,linewise行動作)。如果你想要 "Y" 執行從游標到行尾的操作 (更合乎邏輯,但是與 Vi 不相容),用 ":map Y y$"。
{Visual}["x]y抽出高亮文字 [到暫存器 x] (關於 {Visual} 見Visual-mode)。
{Visual}["x]Y抽出高亮行 [到暫存器 x] (關於 {Visual} 見Visual-mode)。
["x]p放置文字 [從暫存器 x] 在游標之後 [count] 次。
["x]<MiddleMouse>從一個暫存器放置文字在游標之前 [count] 次。除非另外指定,否則用 "* 暫存器。游標停留在新文字的尾部。
["x]gp如同 "p",但游標停留在新文字之後。
["x]gP如同 "P",但游標停留在新文字之後。
Ex CommandUsage
:reg[isters]顯示所有編號和命名暫存器的型別和內容。但不列出用於 :redir 目的地的暫存器。型別可以是以下之一: "c" 用於 characterwise 文字; "l" 用於 linewise 文字; "b" 用於 blockwise-visual 文字
:reg[isters] {arg}顯示 {arg} 裡提到的編號和命名暫存器的內容。例如: :reg 1a
:di[splay] [arg]和 :registers 相同。
:[range]y[ank] [x]抽出 [range] 所指定的行 [到暫存器 x]。僅當包含+clipboard特性時才可以抽出到 "* 或 "+ 暫存器。
:[range]y[ank] [x] {count}從 [range] 的最後一行開始 (預設: 當前行cmdline-ranges) 抽出 {count} 行 [到暫存器 x]。
:[line]pu[t] [x]放置文字 [從暫存器 x] 在行號 [line] (預設為當前行) 之後。
:[line]pu[t]! [x]放置文字 [從暫存器 x] 在行號 [line] (預設為當前行) 之前。
:[range]co[py] {address}把 [range] 指定的行復制到 {address} 給出的行之下。
:[range]m[ove] {address}把 [range] 指定的行移動到 {address} 給出的行之下。

put總是 linewise 行動作,因而這個命令可以用來把抽出的塊放置在新行上。暫存器也可以是 '=',跟隨一個可選的表示式。表示式繼續到該命令結束為止。你需要在 '|' 和 '"' 字元前加上反斜槓不讓它們終止你的命令列。例如: :put ='path' . \",/test\" ;如果 '=' 之後沒有表示式,Vim 使用前一個表示式。用 :dis = 你可以看到它。

上面這些命令也可以用於global命令, 詳細列表檢視help ex-cmd-index

暫存器型別:

  1. 無名暫存器 ""
    用 "d"、"c"、"s"、"x" 等命令刪除或者用 "y" 等抽出命令複製的文字都被 Vim 用來填
    充該暫存器
  2. 10 個編號暫存器 "0 到 "9
    Vim 把抽出和刪除命令的文字儲存在這些暫存器裡。
  3. 行內刪除暫存器 "-
    該暫存器儲存刪除不到一行內容的命令的文字
  4. 26 個命名的暫存器 "a 到 "z 或者 "A 到 "Z
    Vim 只有在你指定的時候才使用這些暫存器。指定為小寫字母時替換原來的內容,指定為大寫字母時附加到原來的內容。
  5. 三個只讀暫存器 ":、". 和 "%
    ". 包含最近插入的文字
    "% 包含當前檔名
    “: 包含最近執行過的命令列。
  6. 輪換緩衝區暫存器 "#
    包含當前視窗buf檔名
  7. 表示式暫存器 "=
    其實並沒有這麼一個暫存器,這是可讀寫的
  8. 選擇和拖放暫存器 "*、"+ 和 "~
    用這些暫存器來儲存和取得 GUI 介面選擇的文字。 只讀的 "~ 暫存器儲存最近一次拖放操作放下的文字
  9. 黑洞暫存器暫存器 "_
  10. 最近搜尋模式暫存器 "/

常用選項

選項描述
用法:set all顯示所有選項和設定;
:set顯示當前設定的所有選項;
:set num?顯示num選項的當前設定;num可以換成其他選項;
:set num開啟選項與關閉選項;
:set nonumnum可以換成其他選項;
num/nonum是/否顯示行號;
wrap/nowrap是(預設)/否自動換行;
wrapmargin=n設定右邊界的值,當輸入時到達右邊界,並遇到空格時,會自動插入換行;
aw/noaw臨時轉入shell或使用":n"編輯其他檔案時,是/否自動儲存當前檔案已做的修改;
flash/noflash在出錯處使用閃爍提醒/使用嗚叫提醒;
縮排ai/noaiautoindent是/否使用自動縮排方式,新行與前面的行保持—致的縮排;
smartindentsmartindent/nosmartindent:是否使用能識別類C語法的智慧縮排方式;
cindentcindent/nocindent:是/否使用cindent縮排方式;
indentexprindentexpr/noindentexpr:是/否使用indentexpr縮排方式;
indenttype=縮排方式:autoindent、smartindent、cindent、indentexpr(同上);
shiftwidth=n自動縮排字元數;
tabstop=n將TAB鍵的寬度設定為n個寧符寬度,預設為8;
編碼encoding=設定vim內部使用的編碼字符集;如:prc;
fileencoding=設定當前編輯的檔案的字元編碼方式;如:utf-8;
fileencodings=設定vim自動探測fileencoding的順序列表;如:"ucs-bom,utf-8,latin1";
termencoding=vim工作的終端的編碼方式;如:utf-8;
ambiwidth=設定漢字所佔字元寬度;如:double;
搜尋ic/noic搜尋時忽賂大小寫/不忽略大小寫(預設);
wrapscan在搜尋時到達檔案尾後是/否跳檔案頭繼續搜尋;
incsearchincsearch/noincsearch:輸入搜尋關鍵字時,是/否(預設)自動高亮匹配的字元;
hlsearchhlsearch/nohlsearch:搜尋後,是/否(預設)保留匹配字元的高亮顯示
程式設計syntax=on/off:是/否顯示語法高亮;
儲存ro/noro是/否只讀模式,只讀模式寫只能通過強制方式":w!"寫入,否則無法寫入;
history=nhistory記錄的行數,預設100個歷史記錄;
filefiletype on偵測檔案型別;
filetype plugin on載入檔案型別外掛;
filetype indent on為特定檔案型別載入相關縮排檔案;
report=n複製或者刪除了多少行時顯示提示資訊,預設為2;
laststatus=0,1,2是否顯示狀態列,0:不顯示,1:需要時間顯示,2:總是顯示;
list/nolist是/否將tab、換行符使用替代字元顯示(^I、$);
shell=path設定vim執行外部命令時使用的shell路徑,如:/bin/bash;
showmatch設定輸入右半邊括號時,是/否(預設)提示所對應的左半邊括號;
showmode設定是(預設)/否在視窗左下角顯示當前的模式:插入、替換等模式;
compatible除非.vimrc檔案存在,預設vim會嘗試採用vi相容的模式;

正規表示式

  1. 表示目標字元的元字元
元字元說明
.匹配任意字元
[abc]匹配方括號中的任意一個字元,可用-表示字元範圍。如[a-z0-9]匹配小寫字母和數字
[^abc]匹配除方括號中字元之外的任意字元
\d匹配阿拉伯數字,等同於[0-9]
\D匹配阿拉伯數字之外的任意字元,等同於1
\x匹配十六進位制數字,等同於[0-9A-Fa-f]
\X匹配十六進位制數字之外的任意字元,等同於2
\l匹配[a-z]
\L匹配3
\u匹配[A-Z]
\U匹配4
\w匹配單詞字母,等同於[0-9A-Za-z_]
\W匹配單詞字母之外的任意字元,等同於5
\t匹配<TAB>字元
\s匹配空白字元,等同於[\t]
\S匹配非空白字元,等同於6
  1. 需要轉義的字元
元字元說明
\*匹配* 字元
.匹配. 字元
\/匹配 / 字元
\匹配 \ 字元
\[匹配 [ 字元
\]匹配 ] 字元
  1. 表示數量的元字元
元字元說明
*匹配0-任意個
\+匹配1-任意個
\?匹配0-1個
\{n,m}匹配n-m個
\{n}匹配n個
\{n,}匹配n-任意個
\{,m}匹配0-m個
  1. 表示位置的元字元
元字元說明
$匹配行尾
^匹配行首
\<匹配單詞詞首
\>匹配單詞詞尾
  1. 表示子模式的元字元

\()括起來的正規表示式,在後面使用時可以依次用\1, \2等變數來表示括號裡的內容

  1. 表示非列印字元的元字元
元字元說明
\n表示匹配 一個換行符。
\r表示匹配 一個回車符。
\t表示匹配 一個製表符 ( Tab 鍵)。
\s表示匹配 任意一個空白字元,包括空格、製表符、換頁符等。
\S表示匹配 任意一個非空白字元。

替換

substitue的縮寫是s, 基本語法是: [range]substitue/search/replace/[flags] [count]

對 [range] 指定的行把 {pattern} 的匹配替代成 {string}。關於 {pattern},參見 |pattern|。{string} 可以是按本義出現的字串,也可包含特殊字元。參見 |sub-replace-special|。如果不指定 [range] 和 [count],僅在當前行進行替代。如果指定 [count],在 [range] 最後一行開始的 [count] 行進行替代。如果不指定 [range] ,則從當前行開始。[count] 必須為正數。另見 |cmdline-ranges|。
  1. range

range是同一個或多個被,;分割的行限定符組成。當用;時, 游標位置會被設定為前一個行限定符確定的行值。

如果行限定符個數多於命令需要的數量,那麼前面的限定符被忽略。

行號可以用下列符號:

符號行號
{number}行號
.當前行
$檔案的最後一行
%相當於 1,$ (整個檔案)
't標記 t 的位置 (小寫)
'T標記 T 的位置 (大寫);如果標記存在於另一個檔案中,則不能在範圍裡應用。
/{pattern}[/]下一個 匹配 {pattern} 的行
?{pattern}[?]前一個 匹配 {pattern} 的行
\/下一個 與前次搜尋模式匹配的行
\?前一個 與前次搜尋模式匹配的行
\&下一個 與前次替代模式匹配的行

這些符號後面可以跟一個或多個+-和一個可靠數字,如果數字省略,則認為是1
/?前面可能有另一個地址,那麼查詢就從那裡開始。如果使用;, 那麼游標會移動

/pat1//pat2/ :不移動游標
7;/pat2/ : 游標留在第7行

例子:

.+3
/that/+1
.,$
0;/that
1;/tath

  1. replace中的特殊字元
nomagic動作
\&替代為完整的匹配
&替代為 &
\0替代為完整的匹配
\1替代為匹配的第一個 () 裡面的內容
\2替代為匹配的第二個 () 裡面的內容
....
\9替代為匹配的第九個 () 裡面的內容
\~替代為前一個 substitute 的替代字串
~替代為 ~
\u下一個字元成為大寫
\U其後字元成為大寫,直到 \E 出現
\l下一個字元成為小寫
\L其後字元成為小寫,直到 \E 出現
\e結束 \u、\U、\l 和 \L (注意: 不是 <Esc>!)
\E結束 \u、\U、\l 和 \L
<CR>把該行在此位置一分為二 (<CR> 以 CTRL-V <Enter> 方式輸入)
\r同上
\<CR>插入一個回車 (CTRL-M) (<CR> 以 CTRL-V <Enter> 方式輸入)
\n插入一個 <NL> (檔案裡的 <NUL>) (此處並不是換行)
\b插入一個 <BS>
\t插入一個 <Tab>
\\插入單個反斜槓
\x其中 x 是上面沒提到的任何一個字元: 保留作將來的擴充套件

\1\2 等裡的數字是基於模式裡 \( 出現的順序 (從左到右)。如果一個括號組匹配多次,最後一次的匹配被使用在 \1\2 等裡。例如:

:s/\(\(a[a-d] \)*\)/\2/      # 修改 "aa ab x" 為 "ab x"

\2 對應 \(a[a-d] \)。第一次匹配 "aa ",第二次匹配 "ab ", 最後一次匹配"ab "被用於\2

  1. Flags
FlagsUsage
`&必須是首個使用的標誌位,保留和上次substitue相同的標誌位`
`c` 確認每個替代
`e` 如果搜尋不成功,不給出錯誤資訊
`g` 對行內所有匹配進行替代
`i` 忽略模式的大小寫
`I` 不忽略模式大小寫
`n` 只報告匹配次數,不實際進行替代
`p` 顯示包含最後一次替代的行
`#` 類似p, 且在前面加上行號
`l` 類似p,但顯示方式類似:list
`r` 如果匹配模式為空,優先使用上一次使用的搜尋模式,之後再是上一次substitute或global使用的模式
  1. 示例
:s/a\|b/xxx\0xxx/g               # 修改 "a b"     為 "xxxaxxx xxxbxxx"
:s/\([abc]\)\([efg]\)/\2\1/g     # 修改 "af fa bg" 為 "fa fa gb"
:s/abcde/abc^Mde/                # 修改 "abcde"    為 "abc"、"de" (兩行)
:s/$/\^M/                        # 修改 "abcde"    為 "abcde^M"
:s/\w\+/\u\0/g                   # 修改 "bla bla"  為 "Bla Bla"
:s/\w\+/\L\u\0/g                 # 修改 "BLA bla"  為 "Bla Bla"
:s/aa/a^Ma/                      # 修改 "aa"  為 a<line-break>a
:s/aa/a\^Ma/                     # 修改 "aa" 為    a^Ma
:s/aa/a\\^Ma/                    # 修改 "aa" 為 a\<line-break>a

多檔案編輯

  1. 已經開啟一個檔案

    • 開啟一個新檔案
      edit[!] foo.txt
    • 儲存
      write
  2. 開啟多個檔案
    vim one.c two.c three.c
    然後可以用:[num]next, :wnext:[num]previous, :wprevious, :last, :first來切換
  3. 多檔案跳轉
    可以用args one.c two.c three.c來新增多個檔案
    然後可以用CTRL-^來切換到上一個檔案
    有兩個標記非常重要:

     `'"`: 你上次離開這個檔案的位置
     `'.`: 你最後一次修改檔案的位置

    可以用m[a-zA-Z]來標記檔案, 然後用'[mark]來跳轉
    還可以用CTRL-OCTRL-I來在整個跳轉序列中前後跳轉

多視窗

分割視窗

可以直接用vim -O one.c two.c來直接以分割方式開啟多個檔案
-O : 垂直分割
-o : 水平分割

如果已經開啟檔案,可以使用命令來開啟/關閉視窗

:sp[lit] {file}     水平分屏
:new {file}         水平分屏
:sv[iew] {file}     水平分屏,以只讀方式開啟
:vs[plit] {file}    垂直分屏
:clo[se]            關閉當前視窗
:only               只顯示當前視窗

上述命令都有快捷鍵, 共同字首是: CTRL-W

Ctrl+w s        水平分割當前視窗
Ctrl+w v        垂直分割當前視窗
Ctrl+w q        關閉當前視窗
Ctrl+w n        開啟一個新視窗(空檔案)
Ctrl+w o        關閉除當前視窗之外的所有視窗
Ctrl+w T        移動當前視窗到新標籤頁

切換視窗

Ctrl+w h        切換到左邊視窗
Ctrl+w j        切換到下邊視窗
Ctrl+w k        切換到上邊視窗
Ctrl+w l        切換到右邊視窗
Ctrl+w w        遍歷切換視窗

移動視窗

Ctrl+w H        向左移動當前視窗
Ctrl+w J        向下移動當前視窗
Ctrl+w K        向上移動當前視窗
Ctrl+w L        向右移動當前視窗

調整視窗大小

Ctrl+w +        增加視窗高度
Ctrl+w -        減小視窗高度
Ctrl+w =        統一視窗高度

對映

$$ <map command> <args> {lhs} {rhs} $$

command

Command NormalVisualOperator PendingInsert OnlyCommand Line
命令 常規模式視覺化模式運算子模式插入模式命令列模式
:mapnoremapyyy
:nmapnnoremapy
:vmapvnoremap y
:omaponoremap y
:map!noremap! yy
:imapinoremap y
:cmapcnoremap y

Operator-pending模式,是指當你輸入操作符(比如d)時,然後繼續輸入的移動步長和文字物件(dw)的狀態

nore的含義是, 禁止對{rhs}再進行對映掃描,以防止巢狀和遞迴,通常用於重定義一個命令

args

<buffer><nowait><silent><special><script><expr><unique> 可以按任意順序使用。它們必須緊跟在命令的後邊,而在其它任何引數的前邊。

<buffer> : 只作用於當前buffer
<silent> : 不回顯命令
<script> : 只能使用<SID>開關的指令碼來對映{rhs}
<unique> : 如果對映或縮寫的命令已存在,只命令失敗
<expr> : 那個{rhs}是一個表示式,會用計算後的返回值代替{rhs}

強大的gv

:global 命令是 Vim 中一個更強大的命令 (之一)。它允許你找到一個匹配點並且在那裡執行一個命令。它的一般形式是:

:[range]g/{pattern}/{command}

在每一匹配行上執行命令command. 這個命令只能是冒號命令, 普通模式命令不能在這裡使用。如果需要,可以使用:normal命令。

如果要檢視可以使用的命令,可以help ex-cmd-index。 如果要檢視詳細解釋, 檢視help 10.4help multi-repeat

vglobal相當於global!, 兩者可以組合使用, 如:g/found/v/notfound/{cmd}

利用global我們可以把我們之前學的很多東西都串連起來,以完全一些非常奇妙的動作。

簡單示例,

  • 要刪除所有空行: :g/^$/d
  • 要在含有always..begin的行後加上:label: :g/always.*begin/s/$/ :label

exec和normal

execute命令用來把一個字串當作Vimscript命令執行。比如: :execute "rightbelow vsplit " . bufname("#")

normal命令把我們的指令碼跟日常的文字編輯按鍵結合起來, 比如: :normal ggdd。 為了防止遞迴解析, 建議永遠使用normal!

利用exec和normal的組合可以將動作變成可重複的命令, 並消除轉義字元問題。比如: :execute "normal! mqA;\<esc>'q"


  1. 0-9
  2. 0-9A-Fa-f
  3. a-z
  4. A-Z
  5. 0-9A-Za-z_
  6. \t

相關文章