本文也即《Learning the bash Shell》3rd Edition的第二章 Command-Line Editing之讀書筆記。但我們將不限於此。
我一般的使用方式,就是直接敲,如果敲錯了,用左右游標箭回去修改,或者使用上下游標鍵直接使用以前的命令或在以前的命令進行修改。似乎僅此而已。我用vi,幾乎不使用emacs。這本書的作者說可以如同使用vi或者emacs那樣編譯命令,期待中,我還專門在cygwin上裝了emacs。
曆史命令記錄在~/.bash_history,這是由HISTFILE決定的。可以用echo $HISTFILE來查看。當我們登入login或者開啟某個terminal進行shell人機互動的使用,bash從.bash_history中取出以前的曆史命令。在cgywin中,當我們exit視窗時,會進行儲存,不是每個bash即時儲存,但是對於其他linux,不能確定。我們用上下游標鍵可以得到曆史命令,可以通過history命令將他們全部列出(包括尚未寫入HISTFILE的命令)。
Emacs模式
預設的,bash使用emacs模式進行編譯,可以用set –o emacs|vi,來指定我們使用的方式。下面介紹一下編譯方式:
一、對字元的操作
:這本書介紹的主要基於keybroad的操作,比較古老的方式,例如沒有游標鍵,也例如在某些遠程操作中,例如串口串連,無法使用游標鍵的情況。這些情況在現在已經比較少出現,所以我們並不需要去記憶他們。下面僅做抄錄。當我們修訂好,無需將游標移到最後,可以之間按斷行符號鍵執行命令。
- CTRL-B,游標後移(左移),相當於左向游標
- CTRL-F,游標前移(右移),相當於右向游標
- DEL,刪除後面一個字元(其實就是刪除當前字元,游標前移)
- CTRL-D,刪除前面一個字元(其實就是刪除當前字元,游標後移),這個需要小心,因為如果什麼都沒有,按CTRL-D,相當於logout或者關閉這個terminal。
二、對word的操作
:我一直都沒有使用過基於word的操作,都是土土地使用字元方式,其實也沒什麼關係,it still works。對於emacs模式,字幕和數字作為一個word,如果中間使用“-”,會認為是兩個word。
- ESC-B,游標向後移動一個word
- ESC-F,游標向前移動一個word
- ESC-DEL,刪除當前或者後面的word,實際上我在cgywin裡面並沒有起作用
- ESC-CTRL-H,刪除前面的word,或者word的游標前面部分
- ESC-D,刪除後面的word,或者word的游標後面部分
- CTRL-W,刪除前面的word,或者word的游標前面部分
- CTRL-Y,回複之前刪除的部分。
三、對行的操作
:如下:
- CTRL-A,游標移到最前,相當於Home,所以不必要記憶那麼多
- CTRL-E,游標移到最後,相當於End,所以不必要記憶那麼多
- CTRL-K,刪除當前游標到最後的內容,可以用CTRL-Y進行恢複。實際上CTRL-Y,將上次操作被刪除的部分記憶下來,在當前游標出parse。
四、對曆史命令的操作
:這是非常常用的,實際上,我們簡單地通過上下游標鍵就可以實現,下面作為記錄:
- CTRL-P,前一命令,同上游標鍵
- CTRL-N,後一命令,同下游標鍵
- CTRL-R,查詢,如果沒有查到,會發出beep
- ESC-<,history的第一條命令,我在cgywin中實驗,無效
- ESC->,history的最後一條命令,我在cgywin中實驗,不太穩定
五、完整文字的操作
:我們不希望敲一個很長的命令,或者很長的檔案名稱字,我們只需要敲入前面的字母,在沒有歧義的情況下,可以自動顯示完整的word,我只會用TAB。包括路徑、命令、function都可以使用這種方式來簡化我們的輸入,command和function比路徑(檔案名稱)有更高的優先權。除了給出prefix外,我們可以直接按tab,給出後面匹配的內容,或者經可能長地給出後面匹配的內容,例如我們有兩個檔案abc123和abcdef,我們按tab,可以得到abc,後面無法精確匹配。如果我們不清楚具體的名字,我們可以再按tab,則系統給出abc123,abcdef,供我們參考。
- ESC-?,可以顯示可能用於完善的命令,作用類似於連續的tab
- ESC-/,嘗試檔案名稱完整
- CTRL-X /,顯示可能的完整檔案名稱
- ESC-~,嘗試可能的完整使用者名稱(實際上要按三個鍵,因為~需要按shift鍵)
- CTRL-X ~,顯示可能的完整使用者名稱,我在cgywin中實驗,無效
- ESC-~,嘗試vairable 完整,不確定什麼意思
- CTRL-~,列出vairable 完整,不確定什麼意思
- ESC-@,嘗試hostname的完整
- CTRL-@,列出hostname的完整
- ESC-!,嘗試命令完整
- CTRL-X !,這個表示先按CTRL-X,後按!(shift-1),列出所有可能的命令完整
- ESC-TAB,嘗試根據history list來完整命令
六、其他一些操作
:我覺得如斯之操作,估計都是記不住的,僅在此記錄下來,讓我們瞭解一些bash能提供多少編輯能力。
- CTRL-J,等同於RETURN,即斷行符號,在ASCII中為LINEFEED,UNIX中允許用之來替代RETURN
- CTRL-L,類似於clear,清空螢幕,並放置在螢幕的最上端
- CTRL-M,等同於RETURN,即斷行符號
- CTRL-O,等同於RETURN,然後顯示在history中下一條命令
- CTRL-T,將兩個字元交換位置
- CTRL-U,刪除開始到游標所在處
- CTRL-V,加入quote,但是我在cgywin中無效
- CTRL-[,等同於Esc
- ESC-C,將字母變為大寫,並游標移到下一個word處
- ESC-U,將word的位於游標即後面的字母變為大寫,並游標移到下一個word處
- ESC-L,將word的位於游標即後面的字母變為小寫,並游標移到下一個word處
- ESC-.,將上一命令的最後的word加入游標所在處
- ESC-_,同ESC-.
Vi模式
vi模式不是預設的方式,需要通過set –o vi進入。 vi是很好的文本編譯器,例如用於C編程,但是在bash上,可能會比Emacs要敲更多的鍵。分為輸入模式和控制模式。
輸入模式
下包括:
- DEL:刪除字元,游標後移
- CTRL-W:刪除之前的word
- CTRL-V:Quote the next character,在cgywin中無效
- ESC:進入控制模式
在控制模式
中,可以進行下面的編譯方式。在vi中word分兩種方式,一種叫non-blank,這是用空格作為劃分的word,一種是有字母數字組成的word,預設我們指後面一種。
控制模式——移動
- h,左移一個字元
- l,右移一個字元
- b,左移一個word
- w,右移一個word
- W,移到下一個non-blank的word
- B,移到上一個non-blank的word
- e,移到當前word的最後
- E,移到當前non-blank的word的最後
- 0,移動行最前
- ^,移到行第一個non-blank的word
- $,移到行最後
出來最後三個方式,我們可以用數字表示重複的操作,例如7h,相當於連續按了7次h。
控制模式——重新進入input:
我們進入control模式後,希望退出,重新進入input模式,可以通過下面幾種方式:
- i,表示當前插入
- a,表示後面加入
- I,表示在行最開始加入
- A,表示在行最後加入
- R,表示重寫(r表示更換某個字元,仍然在控制模式下)
控制模式——刪除:
vi模式提供了很強大的刪除功能,即使我非常熟悉vi,有一些仍然是我少用的。記錄如下:
- dh:刪除一個字元,游標後移
- dl:刪除一個字元,游標前移
- db:刪除當前游標所在word的前面部分,如果游標不位於word中刪除游標的前一個word
- dw:刪除當前游標所在word的後面部分,如果游標不位於word中刪除游標的後一個word
- dB:刪除當前游標所在non-blank word的前面部分,如果游標不位於non-blank word中刪除游標的前一個non-blank word
- dW:刪除當前游標所在non-blank word的後面部分,如果游標不位於non-blank word中刪除游標的後一個non-blank word
- d$:刪除游標到最後的部分
- d0:刪除開始到游標的部分
如果我們用c代替d,則執行刪除命令後,進入input模式。,另外還可以使用一些縮寫:
- D:相當於d$,刪除游標到最後的部分
- dd:相當於0d$,即刪除整行
- c:相當於c$,即刪除後面部分,並進入input模式
- cc:相當於0c$,即刪除整行,並進入input模式
- X:相當於dl,刪除一個字元,游標前移
- x:相當於dh,刪除一個字元,游標後移
所有好的編輯器都提供un-delete的方式。在vi模式中,用u可以回複之前的操作,能一直追溯。對於刪除命令中,如果我們用y代替d,我們將記錄原來使用d命令所要刪除的部分,當時並不實際刪除,用p(游標之後)或者P(游標之前)命令可以將這個記錄內容粘帖出來。
控制模式——History命令:
如下
- k或者-,之前命令,相當於向上游標,可以使用3k表示重複3次
- j或者+,之後命令,相當於向下游標,可以使用3j表示重複3次
- G,Move to line given by repeat count,不確定含義
- /string,向後尋找含有string的曆史命令,而^string,用於查詢開頭是string的曆史命令,可以用/進行繼續尋找
- ?string,向前尋找含有string的曆史命令,可以用?進行繼續尋找
- n,繼續原來的方向繼續尋找
- N,在原來相反的方向繼續尋找
我們看到使用h、j、k、l,實際上他們就是最古老的游標鍵。這種鍵盤在很久以前見過。不記得買的第一個鍵盤是怎麼樣子的,只記得第一個顯示器在一聲巨雷後,冒出靄靄白煙,報廢了,還好,當時不是坐在電腦前。
控制模式——尋找字元:
下面是尋找的方式,x表示某個字元。下面的這些命令在前面都可以加上重複操作的次數n,例如4fa,向後尋找第4個a字母
- fx,尋找下一個字元x,游標移到該x上
- Fx,尋找上一個字元x,游標移到該x上
- tx,尋找下一個字元x,游標移到該x的前一個字元上
- Tx,尋找上一個字元x,游標移到該x的後一個字元上
- ;,重新操作上個尋找命令
- ,,重新操作上個尋找命令,但是尋找的方向相反
此外我們還可以根據column,即第N個字元來尋找,即n|。如果只敲|,則為第一個字元。
控制模式——完整操作
:
- /,等同於emacs模式的TAB,可以完整後面的命令、function、檔案名稱
- *,完整檔案名稱,如果有多個選擇,將他們都列出來(在命令列中列出)
- =,完整檔案名稱,如果有多個選擇,將他們都列出來。
控制模式——其他動作
- ~,更換當前字母的大小寫,游標後移
- -,給出上個命令的最後word,並進入input模式,在cgywin中,不太靈光
- CTRL-L,清屏
- #,這個會自動加最前面,命令將不會被進行,但會被記錄在history中。
fc處理曆史命令
fc是個很有趣的命令。這個命令我以前沒用過,我使用history,或者上下游標箭頭來查閱或者擷取曆史命令。
- fc -l,顯示曆史命令,後面可以更參數,如果數字,表示第N個命令,如果是字串,表示最近以該字串開頭的命令。如果有兩個參數,則表示顯示範圍內的命令,例如fc -l 5 8,顯示第5-8的命令,如果只有一個參數,表示從該命令開始顯示,例如fc -l 5,顯示第5到最後的曆史命令。
- 出來顯示曆史命令,還可以直接編譯曆史命令,例如編譯第45號命令,fc 45,編譯最近以c開頭的命令,fc c,這樣,這個命令就進入vi的編譯模式,我們在那裡很方便編譯。如果我們給出兩個參數,我們就可以編譯一個名字組,退出vi模式後,依次執行這些命令
。
其他
書中還介紹了一些擴充的曆史命令的處理方式,我覺得看看就可以了,誰記得這麼多的東西,就像中文打字一樣,以前學過什麼自然碼,但是真正能記住的就是拼音。而且我在cgywin中實驗,並沒有起什麼效果。這一章節的關鍵在於我們能夠方便對bash進行編譯,就可以了。
bash的edit介面成為readline,我們可以通過~/.inputrc的修改來修訂readline,從而設定我們自己特色的按鍵方式。這類檔案稱為startup檔案。檔案中,將一個(組)key和一個macro或者readline的function向關聯。例如我們想增加CTRL-T,將游標放置行後面,我們在.inputrc中加入:
#wei test
“/C-t”: end-of-line
其中”/C-t”是key名字,/C表示Control鍵的首碼,後面end-of-line是readline的function,有操作60這種這樣的功能。第一行加#表示注釋。這也可以提供一種快捷的方式,例如“/C-t”: “Hello”,則當我使用CTRL-T,等同於敲入Hello。
- /C-:CTRL鍵
- /M-:Escape鍵(Meta(Escape) key prefix)
- /e:escape charater,在實驗中,和/M-沒有什麼區別
- //:表示/;/”,表示”,/’表示’
我們可以加入一些條件控制,例如只針對某種edit模式,某類teminal或者某些應用。條件控制使用$if,$else,$endif,例如上面例子只出現在emacs模式下。
$if mode=emacs
“/C-t”: end-of-line
$endif
對於一些快速鍵,可以用bind -P
來查看。在.inputrc檔案中修改,需要在下次login時有效,但是有時我們不希望永久修訂,只希望臨時能夠起效,可以使用bind ‘“/C-t”: end-of-line’的方式,bind後面的設定同startup檔案中的處理,但是需要加上’’。bind只在本次登入有效。清除捆綁,使用bind –u ,所有該function的捆綁都清楚,可以用bind -P來確認。bind –r ,該快速鍵失效。bind -x用於捆綁shell命令,例如bind –x ‘"/C-l":ls'。刪除特定的捆綁,正如我們使用bind來增加綁定一樣。 bind -p比較有趣,按.inputrc中的格式顯示,可以匯入.inputrc中,也可以copy一下放入bind命令中。如果我們需要自訂很多的這類的命令,而又不想放入.inputrc中,我們可以將它們寫入某個檔案,通過bind -f 匯入。
我們也可以通過set方式來設定一些readline的參數,有很多參數可以設定,具體閱讀《Learning the bash Shell》,這裡我列一下我感興趣的:
set bell-style none|visible|audible,預設是audible,這個設定用於處理beep的情況,例如tab沒有匹配會發出beep,如果在辦公室,老是beep beep的,挺煩的,可以關閉none,visible的方式在cgywin中和audible沒有區別。
總結
實際上,即使我們經常使用linux,我們仍很難記住這麼多的東東,而且現在的鍵盤已經相當方便,或許在一些串口的teminal中會有一些限制。一般來講,我們使用如下的基本上足夠:
- 左右游標鍵,Home和End將游標移至行頭和行尾
- 上下游標鍵,翻看曆史命令
- tab鍵,自動盡量補齊完整的詞
- Del或者backspace進行刪除
- CTRL-C,放棄整行,不執行
相關連結:
我的Linux操作相關文章