ex是Vim對行編輯器ed的支援.ed是一個面向行的編輯器.在遠古時代,還是黑白終端的時代,有一個流行的面向行的編輯器ed,也即把檔案一行一行的讀入,一次只顯示一行,然後編輯這行.所以Vim中的ex命令都是ed編輯器所支援的命令,現代所用的流編輯器sed中的命令是ed命令的擴充.所以掌握了Vim中的ex編輯命令,稍加變通就連sed也一起搞定了.
Vim是全屏編輯器,因此不會像ed那樣只顯示一行,對於Vim,ed命令編輯的一般都是當前行,這就相當於ed中所顯示的那行,實際上也是檔案的當前行.
命令常識
在Vim中所有的ex編輯命令都是以:(冒號)開頭
啟動方式就是在命令模式下輸入冒號,然後輸入具體命令
在Vim的狀態行(通常為螢幕最下面的一行),會顯示你所輸入的命令,同時也會用於顯示命令的輸出結果.
由於是面向行的編輯命令,所以基本單位是行,比如拷貝和剪下都是以行為單位(也即最少為一行).
命令格式
:[range] cmd args
雜項命令
這些命令跟具體的文本編輯無關,但是也非常的常用
- := -- 列印檔案的總行數
- :/pattern/= -- 列印匹配pattern的行號
- :w -- 把當前buffer寫入檔案,也就是說進行儲存動作
- :w! -- 強制儲存,如果是唯讀檔案也能進行儲存動作
- :q -- 退出當前檔案,前提是已經儲存過了,如果沒有儲存Vim會提醒你的.
- :q! -- 強行退出,也就是說無論已經儲存過與否都退出,可能會丟失所做的修改
- :wq -- 儲存並退出.
- :wa -- 把所有的buffer寫入檔案,也即儲存所有的檔案(如果你開啟了多個檔案的話).
- -- 儲存並退出,程式員最應該使用的命令.它與:wq的區別在於,如果檔案沒有修改:x是不會修改檔案的時間戳記,因此就不需要重新編譯.而:wq命令,即使檔案未修改也會修改時間戳記,也即會觸發重新編譯.
- :xa -- 儲存並退出所有的檔案,如果開啟了多個檔案話.
- :w a-new-file -- 另存新檔a-new-file
- :[range] w a-new-file -- 把[range]所指定的範圍的內容另存新檔a-new-file
- :[range] w >> another-file -- 把[range]所指定的範圍的內容追加到another-file中
- :r file or :read
file -- 把file檔案中的內容讀出來放到當前行下面.細節是開啟file,拷貝其中的內容然後粘貼到當前行下面.
- :n r file -- 把file中的拷貝到第n行下面
- :/pattern/ r file -- 把file中的內容拷貝到第一個匹配pattern的行下面
- :e another-file -- 把another-file讀入記憶體並開始編輯
- :e! -- 捨棄所有的未儲存的修改,回到上一次檔案所儲存的狀態
如何指定範圍[range]
很多命令都需要指定範圍和行號,如何做呢?
0. 不指定行號則通常代表當前行
1. 具體的絕對的行號,行號是從1開始到第x行,x為檔案總行數.
- :n, m -- 檔案的第n行到第m行,包含n和m
如:2, 10則是第2行到第10行
如果n=0或n=-1則n自動轉成1;如果m大於x則轉成x
特殊的行號
如:.,$則表示檔案中的所有行
2. 相對於當前行和相對行號
- +/-n -- +表示從當前向第n行;-表示當前行向前減n行
- +/- -- 前一行或後一行
如:-,+ d -- 刪除當前行,上一行和下一行,共三行;:-2,+2 d刪除當前行,前二行後二行,共五行
用搜尋匹配來指定行
- /pattern/ -- 指定的是匹配pattern的下一行,也即當前行後面的第一個匹配pattern的行.這個只能指定一行
- /pattern/, /pattern2/ -- 第一個含有pattern的行到第一個含有pattern2的行.
注意,如果指定範圍時後面的行號小於前面的行號,那麼Vim會提示你[range]邊界指示反了,要不要swap一下.
重新指定當前行
- n; m -- 把第n行視為當前行.預設情況下游標所在為當前行.這個命令能快速指定當前行,可以省不少的力氣
如:
- :40; +50 d -- 刪除第40行到第50行.這相當於:40跳到40行,然後執行+50 d.
- :/old/; +10 d -- 刪除從含有old的行到其下面的10行.這相當於然後搜尋到含有old的行:/old/,然後執行:+10 d
編輯命令解析
- :[range] d -- 刪除.如:1, 20 d刪除第1到第20行
- :[range] mv target -- 後面需要加上移動的目的地.剪下[range]指定的部分粘貼到target所指定的位置.
- :[range] co/t target -- 把[range]指定的部分拷貝到target位置
- :[range] y/ya -- 複製[range]到剪下板中
- :[range] y name -- 複製[range]到剪下板中,並且命名為a,這樣就可以同時操作多個拷貝
- :n pu -- 把剪下板中的內容粘貼到第n行下面
- :n pu name -- 把剪下板中名字為name的拷貝粘貼到第n行下面
命令列啟動命令
就是開啟後進行一些操作
$vim +n file -- 開啟file檔案後跳到第n行$vim + file -- 開啟file檔案後跳到最後一行$vim +/pattern file -- 開啟file檔案後跳到含有pattern的那行
如,$vim +/"your life" file -- 開啟後跳到"your life"的那行
編輯多個檔案
命令,模式和buffer會在多個檔案和多個視窗之前共用.所以如果同時編輯多個檔案會提升一些效率
1. 命令列啟動多個檔案
$vim a.txt b.txt c.txt
2. 已經在編輯一個檔案時,可以用:e命令開始編輯另外一個檔案
3. args -- 顯示所有的檔案清單,當前的檔案會以[filename]形式標出
$vim a.txt b.txt c.txt:args ----->>>>[a.txt] b.txt c.txt:n ----->>>>a.txt [b.txt] c.txt
4. 在檔案之間進行切換
- :p[rev] -- 前一個檔案
- :n[ext] -- 下一個檔案
- :last -- 最後一個檔案
雙檔案模式
1. 啟動方式:當編輯一個檔案的時候,用e命令讀入並編輯另外一個檔案就進入了雙檔案模式
2. 二個檔案速記符,相當於字串宏,內容就是所編輯的二個檔案名稱
3. 樣本
$vim a.txt:w -- 儲存修改:e b.txt -- 開始編輯另外一個檔案b.txt:e # -- 開始編輯前一個檔案,也就是檔案a.txt:e # -- 開始編輯前一個檔案,這時是b.txt:w %.bak -- 另存當前檔案為b.txt.bak(此時當前檔案%為b.txt):r # -- 拷貝a.txt的內容到b.txt當前行下:split # -- 在新視窗中開啟a.txt:e! # -- 捨棄當前檔案修改,並開始編輯a.txt
組合命令
可以用|來把幾個命令組合在一起使用,與用;來組合Shell命令是一樣的.
如
- :1, 3 d | s/their/they -- 刪除1到3行然後在當前行把their替換為they
獲得協助
對於任意一個命令都可以用
執行Shell命令
- :!cmd -- 執行Shell命令,會跳到Terminal以顯示命令的結果
對於大部分Shell命令可以通過內部來執行
- :cmd -- 執行命令,其操作結果顯示在狀態行裡.
如:cd -- 切換目前的目錄;:ls遍曆目錄內容;:pwd -- 查看當前工作目錄
臨時性的進入Shell
有時候想到到Shell終端進行某些操作,然後還要回來編輯檔案.可以這麼做:
-- 儲存並退出到終端;做想做的事情$do all stuff you want$vim file -- 再次開啟並編輯檔案
這是一個很常用的情境,所以就有了更快捷與方便的方法,可以shell或sh命令來做相同的事情
:sh -- 回到終端$ do you stuff$exit -- 當完事後用exit命令就會退出終端然後回到編輯器.
sh命令很實用.比如常見的編輯編譯運行調試例行,編譯後就可以用:sh命令退出到Shell進行測試和調試,然後再exit到編輯中.
Quickfix讓編輯編譯都不用離開Vim如何編譯
最簡單的方法當然是直接運行gcc命令:
- :!gcc -o list list.c -std=c99 -Wall -lm
這絕對可行,但這很麻煩
Vim中可以使用make命令
但是這隻會使用make的預設隱匿規則,相當弱,比如沒有額外的選項,想指定如Wall或std都是不行的.
當然你可以寫一個makefile,然後就可以開心的直接運行:make就可以了.
但如果沒有makefile怎麼辦呢,特別是某些單個檔案之類的.每個檔案的編譯目標和源碼都不一樣,這時就可以寫一個簡單的makefile,不指定具體的編譯目標和源碼檔案,而只是定義一些簡單的編譯選項和規則:
#makefileLDLIBS= -lmCFLAGS= -g -std=c99 -Wall -Werror
這樣,在Vim中:
- :make list -- 用makefile中定義的規則來編譯list.c
- :make hello -- 用makefile中定義的規則來編譯hello.c
還可以用makeprg命令來指定編譯的目標和規則,但是這個命令不好用,而且每換一個新檔案就要跟著一起改,不如makefile來的方便.
用Quickfix快速修改編譯錯誤
運行了make命令編譯之後,如果有編譯錯誤Vim會以列表形式把編譯錯誤列出,並eQuickfix工具快速幫你定位出錯的行
- :cc -- 顯示編譯錯誤的詳細資料,這些資訊顯示在狀態行裡
- :cn -- 下一個編譯錯誤
- :cp -- 前一個編譯錯誤
- :cw -- 開啟Quickfix視窗.這會在螢幕下面開啟一個新視窗,裡面的內容就是一個編譯錯誤清單
- :cl -- 列出所有的編譯錯誤
Quickfix實際上就是一個編譯錯誤清單,每個Quickfix列表能顯示10個錯誤,所以想看其他的錯誤(如果多於10的話)
- :col -- 前一個列表
- :cnew -- 後一個列表
樣本:一個單檔案的編輯編譯運行和調試:
$vim hello.c
edit edit
:make hello -- 編譯hello
:cc -- 顯示編譯錯誤資訊
:cn -- 下一個
:cn -- 下一個
:make hello -- 編譯 ... Okay
:sh -- 進入Shell
$./hello -- 運行並測試程式, 有Bug
$gdb hello -- 調試 ... 找到了問題
$exit
修複運行時問題
:make hello
:sh
$./hello
$exit -- 回到編輯器
在Vim中使用強大的搜尋神器grep
搜尋匹配神器grep也可以在Vim中使用,使用方式
- :gr/grep [opt] pattern files -- 在files中搜尋匹配pattern,與Shell命令中的grep的使用方式是一樣的.
結果是以Quickfix列表形式給出的,因此Quickfix的命令這裡也適用:
- :cn -- 下一處匹配
- :cp -- 前一處匹配
- :cw -- 開啟Quickfix列表,裡面是超連結,點擊後可以直接進入那個匹配
- :cl -- 相看所有的匹配
這些命令會從一個匹配跳到下一個或上一個匹配.如果超出了這個檔案則會進入另外的檔案.所以能在不同檔案之間跳來跳去.很是強大.
更多的內容請查詢協助:help grep
全域搜尋和替換
這也是用ex命令,因為比較多可以單獨寫一篇,請看這篇文章