2008年8月24日 星期日

vim - 常用指令

先去跑步游泳啦~等一下再來寫~

:[range]s/pattern/string/[c,e,g,i]
range 指的是範圍
% 是目前編輯的文章,# 是前一次編輯的文章。
pattern 就是要被替換掉的字串,可以用 regexp 來表示。
string 將 pattern 由 string 所取代。
c confirm,每次替換前會詢問。
e 不顯示 error。
g globe,不詢問,整行替換。
i ignore 不分大小寫。

:n1,n2s/word1/word2/gn1 與 n2 為數字。在第 n1 與 n2 行之間尋找 word1 這個字串,並將該字串取代為 word2 !
例:在 100 到 200 行之間搜尋 vbird 並取代為 VBIRD 則:『:100,200s/vbird/VBIRD/g』。

:1,$s/word1/word2/g從第一行到最後一行尋找 word1 字串,並將該字串取代為 word2 !

:1,$s/word1/word2/gc從第一行到最後一行尋找 word1 字串,並將該字串取代為 word2 !且在取代前顯示提示字元給使用者確認 (confirm) 是否需要取代!

:%s/log.*/log/g收尋目前文件中所有的內容,把log.*取代為log,其中我認為%指的就是目前文件的所有內容

:%!sort -u對目前文件中所有的內容拿來執行sort -u這一個指令,我個人認為%指的就是目前文件的所有內容,而!後面就可以接shell的指令

:!sort -u若上面的指令不加%的話,則不會把指令的結果整個覆蓋在目前的這一個文件中

[補充 2009/01/05]
vi (or vim)是 Unix-like 作業系統下最常用的文字編輯器,操作上跟一般編輯器(如gedit)不同。
以下是基本操作方法:
輸入:a、i、o

到第一行:gg
到最後一行:G
到某一行:xxG
到行首:0
到行末:$

複製:yy
貼上:p
復原:u
把剛剛回復的動作再取消:ctrl-r

刪一個字:x
刪整行:dd

[vim 的環境設定參數]
顯示行數: :set nu
是否自動縮排: :set autoindent
設定按一次tab跳8個空格: :set tabstop=8
使得貼文字時,不會出現整個排版錯誤::set paste
設定用明顯顏色標示要找的keyword: :set hlsearch
設定右下角有狀態列: :set ruler
可以利用倒退鍵 (backspace) 來刪除任意字元。當 backspace 為 2 時,就是可以刪除任意值;0 或 1 時,僅可刪除剛剛輸入的字元, 而無法刪除原本就已經存在的文字了!: :set backspace=2
依副檔名來決定特殊符號的顏色: :syntax on
是否要顯示--INSERT-- 之類的字眼在左下角的狀態列: :set showmode
字串搜尋不區分大小寫: :set ignorecase

vi 的搜尋:/、再次搜尋:n
到 shell::sh(在 shell 中回到 vi:exit

水平分割文字編輯視窗: :split filename
若有指定「檔案名稱」,則新視窗會開啟該檔案; 若沒有指定,則新視窗仍會開啟原檔案。
另外,在編輯視窗中可以利用 ctrl+w 配合方向鍵跳躍選取所要編輯的視窗,
若想要關閉視窗,則在欲關閉視窗裡的命令模式下,
打入離開指令,如: :wq 即可關閉該視窗。

垂直分割文字編輯視窗: :vsplit filename
若有指定「檔案名稱」,則新視窗會開啟該檔案; 若沒有指定,則新視窗仍會開啟原檔案。
另外,在編輯視窗中可以利用 ctrl+w 配合方向鍵跳躍選取所要編輯的視窗,
若想要關閉視窗,則在欲關閉視窗裡的命令模式下,
打入離開指令,如: :wq 即可關閉該視窗。

儲存::w
離開::q
儲存兼離開::wqshift+zz
強制離開(不儲存)::q!
設定儲存的檔名: :w filename

另外,加入vim的圖解鍵盤指令


[2009.03.10 補充]
Q: 如何透過指令輸入連續輸入
input int[0]
input int[1]
input int[2]
input int[3]
A:
:for i in range(0,3) | put ='input int[' . i . ']' | endfor
語法就是script的語法,而我猜那一個 | 是應該就是有一點像是大括號的意思,把要實作的與for語法區隔開來。而,中間的小數點「.」是表示連接前後變數與字串的作用

[2009.10.18 補充]
Q: 如何同時註解掉多行程式碼
A: 在normal mode按crtl+v進入選取模式,選取要mark的行數,如下圖

再按I,在最前面加入「// 」,再Esc,可以以出現你要的結果了!

Q: 如何記錄上次編輯的時候編輯到哪裡了?
A: 在開啟新的檔案的時候,在normal mode先按「`」再按「"

Q: 如何使用vim的語法,去尋找第一個不是"123456"的行
A: vim 的否定語法是 \@!
使用搜尋則是 /^\(.*123456.*\)\@!/^\(\(.*123456.*\)\@!\).*

Q: 在寫程式的時候,常會用到大括號之類的,當我在其中一個符號上時,如何知道其相對應的符號是在哪裡?
A: 在normal mode中,把指標移到其中一個符號上,再按%,就可以跳到其相對應的符號上了

Q: 在windows下寫的純文字檔會在每一行的最後,會產生一個^M換行控制碼,那麼要如何把它移掉哩?
A: 是利用字串取代:
:%s/\r//g

Q: 如何利用vim內建的功能去計算每一個字串(例:int)出現的次數
A: :%s/int//gn

Q: 已經開啟一個檔案之後,如何透過tab開啟另一個檔案
A: :tabedit file.name
相關指令: :tabprev:tabnext:tabmove < index>:tabnext < index>

[2009.12.08 補充]
K
函式查詢
若您在 VIM 中撰寫 C/C++ 程式,可以在 C/C++ 標準函式厙提供的函式名字上按「K」,便可以呼叫出 man page 查詢該函式的用法

=
自動程式縮排對齊
若您在 VIM 中撰寫 C/C++ 程式,可以利用「gg」指令將游標移到視窗最上方、利用「v」切換到選取模式、再用「G」將游標移到檔案尾端 (即達到全選的功能),最後按「=」,VIM 便會幫你的程式做自動對齊

[2009.12.19 補充]
"ayy
將本行文字複製到 a 緩衝區。
a 可為 26 個英文字母中的一個,如果是小寫的話,原先的內容會被清掉,如果是大寫的話是 append 的作用,會把內容附加到原先內容之後。"是 Enter 鍵隔壁的那一個同上符號(ditto marks),當然是要和 shift 鍵同時按的。

"ap
將 a 緩衝區的內容貼上。

問題來了!忘記誰是誰的時候怎麼辦?
:reg
(冒號命令)就會列出所有 registers 的代號及內容。
咦!怎麼還有數目字、特殊符號的緩衝區,原來您剛剛刪除(複製)的內容就預設放在 " 這個緩衝區,然後依序是 0,1,2,...9。也就是說您按 p 不加什麼的話,是取出 " 緩衝區的內容。% 指的是目前編輯的檔案,# 指的是前一次編輯的檔案。

.
重複前次的編輯動作,相當好用的一個指令!

*
尋找游標所在處之 word(要完全符合)。

#
同上,但 * 是向前(下)找,# 則是向後(上)找。

g*
* ,但部份符合即可。

g#
# ,但部份符合即可。n, N 之繼續尋找鍵仍適用。

書籤功能
mx x 代表 26 個小寫英文字母,這樣游標所在處就會被 mark。
`x 回到書籤原設定位置。` 是 backward quote,就是 Tab 鍵上面那一個。
'x 回到書籤設定行行首。' 是 forward quote,是 Enter 鍵隔壁那一個。
Vim 對於書籤的擴充功能
小寫英文字母
只作用於單一檔案內。
大寫英文字母
可作用於各檔案間。例如 mA 會在 viminfo 中紀錄下這個檔案及位置,結束 vim,然後再啟動 vim,按 'A 就會回到當初做標記的那個檔案及所在位置(vim 會自動開啟做有 A 標記的檔案)。別懷疑,請自行馬上做個實驗就知道啦!:-)
阿拉伯數目字
可作用於前次編輯的十個檔案。數目字的用法比較特殊,'0 是回到前一次編輯檔案中離開前的最後位置,'1 則是回到前二次編輯檔案的最後位置,依此類推。您不必使用 m 來標示,vim 會自動記憶。很玄吧!其實這是 viminfo 的功能,您要認真追究的話,請 :h viminfo-file-marks。viminfo 關掉,就沒這個功能了!所謂前次指的是前次啟動的 vim。不管是哪一種的書籤,到達 mark 處(或檔案),想返回原來的位置(或檔案),可以按 Ctrl + O。
:marks
得知目前所有書籤的列表。

標示指令
v 小寫 v,這是屬於字元標示(character visual),按下 v 後您就可以移動游標,游標走過的地方就會標示起來。再按一次 v 或按 Esc 鍵就會結束 v-mode。
V 大寫 V,這是行標示(line visual),按下 V 後會整行標示起來(包括行首前空白的部分),您移動上下鍵,會標示多行。再按一次 V 或 Esc 鍵就會結束 v-mode。
Ctrl+v 這是區塊標示(blockwise visual),可縱向標示矩形區域。再按一次 Ctrl+v 就會結束 v-mode。結束 v-mode 的方式亦可使用 Esc 鍵,或統一使用 Ctrl+c。Windows 系統下 Ctrl+v 是複製鍵,可以使用 Ctrl+Q 來替代。
d 刪除標示區內容。
y 複製標示區內容。
c 替換標示區內容。
gq 重排標示區內容。ㄟ…… 是要先標示好才按的。"ay 還能不能用呢?當然可以,這樣就會把標示區內容存於 a 緩衝區中。可以用 "ap 來貼上。
Shift+> 標示區內容向右移一個 Tab。
Shift+< 標示區內容向左移一個 Tab。

視窗操作
凡是視窗操作的按鍵都是由 Ctrl+w 來起頭的,w 就是 window 的意思。

Ctrl+w s 即 :sp(lit),會開一新視窗,且原檔分屬兩個視窗。
Ctrl+w f 開一新視窗,並編輯游標所在處之 word 為檔名的檔案。
Ctrl+w q 即 :q 結束分割出來的視窗。
Ctrl+w o 即 :only! 使游標所在之視窗,成為目前唯一顯示的視窗其它視窗會隱藏起來。
Ctrl+w j 移至下視窗。
Ctrl+w k 移至上視窗。還記得 hjkl 的按鍵移動方式嗎?
:sp 檔名 開另一新視窗來編輯檔案。

shell 命令
:!外部指令 執行外部指令。當然您的指令要在 $PATH 環境變數內。
:!! 執行前一次執行之外部指令。在這裡的 ! 可不是強迫中止喔!
@: 這是 Vim 的一個很特殊的指令,可以重複前一次的冒號命令。
:sh(ell) 執行 shell。使用 exit 回到 vim。

另外,在此補充一下補全的功能。不是只有 Tab 鍵的補全功能喔!也可以使用上下方向鍵,叫出歷史指令,叫出歷史指令可用於冒號命令及尋找命令(/)。例如,您前已下了 :!ps aux 這個指令,您可以按 : 後就直接按向上方向鍵。別忘了!尋找指令也是可以這樣用喔!

:r !commond 這個就妙了!會在游標所在處次一行插入外部指令 commond 執行後的輸出內容。
例如 :r !date 就會插入日期時間。這在 elvis 是會插入在游標所在處那一行。
:n,mw !commond 以 n 至 m 行內之資料,當做外部指令 commond 的 input。這算是相當高級的用法了,初學者大概還用不上,不過印象中留有一個這樣的功能,以後總是會用得上的。
K 大寫 K 會顯示游標所在處之 word 的 man page 系統線上使用手冊。

如何得知目前的設定

:set:se 會顯示所有經過修改的部份,就是和預設值不一樣的部份。
:set all 顯示目前所有設定值內容。
:scriptnames 顯示各種設定檔的所在路徑及其檔名。
:set option? 顯示 option 這設定的目前值。
:option 直接線上設定,有些設定需加 = 後加上設定值內容。
:set nooption 取消該設定。:set 後面是可以多重設定的。例如
:set autoindent noconfirm autowrite,這樣三種設定就會同時重設。

您當然可以改設定檔來改變設定值。在 Vim 也可以使用 :opt[ion] 來直接線上設定,會列出目前的設定,在 set 這個字上按 Enter 即可改變設定,或就直接修改其值亦可,改完後按 :q 就可以了。在簡短說明處按 Enter 則會叫出該部份的說明檔給您參考,您說方不方便?改好後

:mk[exrc] 則會寫入 ~/.exrc 檔
:mkv[imrc] 則會寫入 ~/.vimrc 檔

^M是按 Ctrl+v 後不放再按M,^M 是特殊字元,是一個字元,而不是兩個字元

[2010.01.01 補充]
在收尋的時候,使用\<pattern\>,也就是括號把要找的字串括起來,意思是說,的的確確是找所要的那個字。換句話說,如果文件中只有一個main,但是,若是\<ma\>去尋找的話,那就會找不到。在使用*,則會自動在收尋的字串中,分別在字串的前後加入\<\>;若只是想要找部分相同的字串的話,可以使用g*,就可以找到部分相同的字串。

[2010.01.31 補充]
Q: 如何刪掉由目前這一行刪到第15行
A: 在normal mode的下輸入d15gg
A: 在normal mode的下輸入ma → 跳到要刪除的行號 → d'a

Q: 如何刪掉第6行到第15行
A: :6,15d

Q: 刪除{}夾住的資料
A: 在normal mode的下輸入di{

Q: 刪除()夾住的資料
A: 在normal mode的下輸入di(

[2011.06.27 補充]
Q: 如何重覆貼內容2000次到目前的檔案裡面
A1: 把general buffer的內容重覆貼2000次到檔案最後
:for i in range(0,1999) | put = getreg () | endfor
getreg()可以取得暫存器的值
getreg()預設取得general buffer的內容,而用yy就是存到general buffer內
getreg('*')取得剪貼簿的內容
getreg('/')取得上一次收尋的內容
A1:
在normal mode做以下動作
1. yy
2. 2000p
A2: 把剪貼簿的內容,重覆貼2000次到目前的檔案最後
:for i in range(0,1999) | put = @* | endfor

[2011.09.26 補充]
Q: 把第3到10行的資料,剪下並且貼到22行
A: :3,10move 22

[2014.07.09 補充]
尋找abc字串,並且取代成客製化字串
:let i=1 | g/abc/s//\='xyz_' . i/ | let i=i+1

參考資料:
鳥哥
vi / vim 圖解鍵盤指令
vi 中一些常用的使令
大家來學 Vim 一個歷久彌新的編輯器
基本 VIM 操作指令
vim label of Rickey's pets
VIM Regular Expressions
vihelp
Append general buffer to the end of every line in VI
Making a list of numbers

沒有留言: