- 論壇徽章:
- 0
|
Bash readline 的使用技巧
很多人會(huì)用 Bash,但是很少有人知道 readline 是怎么回事。readline 是一個(gè)強(qiáng)大的庫,只要使用了它的程序,都可以用同一個(gè)配置文件配置,而且用同樣的方法操作命令行,讓你可以方便的編輯命令行。
使用 readline 的程序現(xiàn)在主要有 Bash, GDB,ftp 等。readline 付予這些程序強(qiáng)大的 Emacs 似的命令行編輯方式,你可以隨意綁定你的鍵盤。
術(shù)語解釋
在下文中,我們經(jīng)常提到 "C-x r" 這類鍵操作。"C-x r" 其實(shí)就是按Ctrl-x,然后按 r。同理 "C-M-@" 就是按 ctrl-alt-@(M表示meta, 在 PC 上就是 Alt 鍵),但是其實(shí) @ 是shift-2 (看看你的鍵盤)。所以 "C-M-@" 實(shí)際上要你按 ctrl-alt-shift-2。
但是在配置文件里的鍵序列中,我們把 "C-x r" 表示為 "\C-xr", 把 "C-M-@" 表示為 "\C-\M-@",你自己看看就知道怎么回事了。同理 "Esc a" 別表示成 "\ea"。
這就是 Emacs 里的按鍵的通常標(biāo)記方法。EMACS = Esc Meta Alt Ctrl Shift
技巧篇
在自己配置命令行之前,我們先來看看利用缺省的鍵綁定能夠進(jìn)行的一些巧妙的用法:
第一招:使用以前的命令行參數(shù)
你是否經(jīng)常出現(xiàn)這種情況?你想把 ~/text-browser/ 目錄下的3個(gè).tar.gz文件搬到/usr3/software/,于是你輸入:
$mv ~/text-browser/*.tar.gz /usr3/software/
我想你一定已經(jīng)知道,打入 ~/text 之后按 TAB 就可以補(bǔ)全text-browser這個(gè)長文件名吧?這是Bash 的基本功能。我廢話?好了,就當(dāng)你知道吧。不過今天我要講的東西比這個(gè)復(fù)雜一些。
Go on! 剛剛輸入到這里,你突然想起,應(yīng)該在 /usr3/software/ 下先建立一個(gè)目錄叫browsers,這樣放進(jìn)去的文件比較好管理。
于是你 Ctrl-u,刪掉了這行命令。唉呀,這么長的命令一下就沒了。是不是有點(diǎn)可惜?這還不算麻煩。然后你
mkdir /usr3/software/browser
mv ~/text-browser/*.tar.gz /usr3/software/browser
嗯。TAB 是幫了你不少忙?墒悄銓(shí)際上有更好的辦法來完成這項(xiàng)工作。好吧,看看 readline 怎樣神奇的完成你的任務(wù):
我們回到這種情況:
$mv ~/text-browser/*.tar.gz /usr3/software/
你剛才是按了 Ctrl-u 刪除了所有輸入的東西?上О!你要是按 M-#(也就是按住 PC 機(jī)的 Alt 鍵,再按 #,實(shí)際上就是 Alt-Shift-3),那么 Bash 就會(huì)在這樣最開頭插入一個(gè) "#",然后輸入這行。這樣命令就被作為一行注釋載入了歷史。
這有什么好處?這樣你的這行命令里的內(nèi)容就可以被再次利用?粗耗憬又斎耄
mkdir ...
等等,你是不是想輸入 /usr3/software/?你不用再敲一遍了!直接按 M-.(Alt 加句號(hào)),看看, /usr3/software/ 是不是出現(xiàn)在命令行上了?M-. 就是調(diào)用了 yank-last-arg 函數(shù),把上一條命令的最后一個(gè)參數(shù)放在命令行上。好了,回車吧!
你接著輸入:
mv ...
等等,這下是該輸入 ~/text-browser/*.tar.gz 了。煩不煩?換一種方式吧。請(qǐng)按:"M-1 M-."(把上一條命令的第一個(gè)參數(shù)放在命令行上)。這樣命令行成為了:
mv /usr3/software/browser
怎么成這樣了?看看你的“上一條命令”是什么吧?是……你自己看。所以這個(gè)參數(shù)不是你想要的。那么繼續(xù)再按一次 "M-."?吹搅税桑磕愕拿钚幸呀(jīng)成為:
mv ~/text-browser/*.tar.gz
好。打一個(gè)空格。再按一下 "M-."。命令行變成了:
mv ~/text-browser/*.tar.gz /usr3/software/browser
這就是你想要的!
是不是看起來你還是花了不少工夫?但是想一想,如果你是要執(zhí)行這樣一個(gè)命令呢?
mv /data/ftp/pub/TUG/texmf/tex/latex/CJK/GB/GB.cap \
/usr/local/texlive/texmf-local/tex/latex/CJK/GB/
嗯。記住這個(gè)有用命令:M-. , 它的前面可以用 M-0, ... 作為數(shù)字參數(shù)。
第二招:補(bǔ)全命令名,文件名和變量名
你知道 TAB 可以補(bǔ)全命令行上很多東西?墒悄阌龅竭@種情況的時(shí)候怎么辦?
man a-very-very-long-command-name
你輸入了 man a-ver... 之后,按 TAB,什么反應(yīng)也沒有。因?yàn)?TAB 執(zhí)行的是 “按情況補(bǔ)全”(complete),它看到 man,知道這應(yīng)該是一個(gè)命令,那么它認(rèn)為: “后面應(yīng)該是一個(gè)文件名參數(shù)! 但是你想要的是命令的名字怎么辦?答案:按 "M-!".
再來看:你需要設(shè)置 XMODIFIERS="@im=fcitx"。你輸入了
export XM...
按 TAB? 沒有反應(yīng)。為什么呢?因?yàn)?TAB 的補(bǔ)全想要一個(gè)文件名,而當(dāng)前目錄沒有開頭是 "XM..." 的文件。那么你怎么補(bǔ)全?答案:"M-$"。
其實(shí) readline 的補(bǔ)全方式被 Bash 擴(kuò)充了很多。看看有多少吧!
"TAB": complete
"\M-!": complete-command
"\M-/": complete-filename
"\M-@": complete-hostname
"\M-~": complete-username
"\M-$": complete-variable
自己試試吧!
第三招:擴(kuò)展命令行
你的一個(gè)目錄里有很多類似的文件,名字叫 T12.txt, T12.log, T23.txt, T23.log, T13.txt, T13.log…… 有后綴 txt 的,也有后綴 log 的。... 你想把其中的某些 T*.txt 都移動(dòng)到另外一個(gè)目錄,而T*.log都不動(dòng)。但是T*.txt 也不是全部都要移動(dòng)。所以你想把T*.txt 都放在命令行上,然后選擇其中一些。你輸入:
mv T...
接著按 "M-*"(insert-completions)。結(jié)果 T 開頭的文件都被放到命令行上了。嗯。這在某些時(shí)候是有用的,可是現(xiàn)在它把 T*.log 的文件也放上去了。不行。我們于是繼續(xù)輸入:
mv T*.txt
好了,現(xiàn)在我們可以使用 "C-x*"(先按ctrl-x,然后按*)。結(jié)果所有名字T*.txt 的文件都被放到了命令行上面。"C-x*" 執(zhí)行的函數(shù)叫做 glob-expand-word.
配置篇
你是不是覺得那些命令很難記?不順手?別怕!它們都是可以改變的,就像Emacs的鍵綁定那樣,可以被任意的改變!
所有使用readline的程序,都使用一個(gè)配置文件來決定它的行為和鍵綁定。這個(gè)文件一般是 INPUTRC 環(huán)境變量確定的。如果這個(gè)環(huán)境變量沒有值,那么缺省使用 ~/.inputrc。
~/.inputrc 文件很簡單,只有4種語句:
1.注釋
2.變量設(shè)置語句(set variable value)
3.鍵定("keyseq":function)
4.條件語句($if ... $endif)
我們先不說其它的,先來看看鍵綁定吧!
鍵綁定
1.綁定語句。
你現(xiàn)在就可以動(dòng)手設(shè)置你喜歡的控制方式。比如,我發(fā)現(xiàn)有些時(shí)候我需要在命令行上做上 mark(Emacs 術(shù)語),然后把mark 和光標(biāo)之間的 region(Emacs術(shù)語) 刪掉,這個(gè)操作在 Emacs 里叫做kill-region. 但是我們發(fā)現(xiàn)這個(gè)函數(shù)在 Bash 里缺省是沒有綁定的。如果我希望得到跟 Emacs 一樣的綁定 C-w 的話,就把這行插入到 ~/.inputrc:
"\C-w":kill-region
2.使綁定生效。為了使這個(gè)鍵綁定生效,你需要執(zhí)行 re-read-init-file 函數(shù)。這個(gè)函數(shù)缺省綁定在了 "C-x C-r"。你修改 ~/.inputrc 之后在 Bash 里輸入 "C-x C-r" 就可以使新的配置生效了。
3.列出可用的函數(shù)。
不過你怎么知道那些函數(shù)可以被綁定呢?readline 的 info 頁列出了很多函數(shù),可是你不會(huì)每次都去info里查詢吧,很麻煩啊。其實(shí)你可以使用bash的 bind 命令來得到所有的鍵綁定:
$bind -p
可以顯示所有現(xiàn)有的已經(jīng)綁定和沒有綁定的函數(shù)。沒有被綁定的函數(shù)被顯示為 "(not bound)",并被加上了注釋。就像這樣:
"\C-g": abort
"\C-x\C-g": abort
"\M-\C-g": abort
"\C-j": accept-line
"\C-m": accept-line
# alias-expand-line (not bound)
# arrow-key-prefix (not bound)
# backward-byte (not bound)
"\C-b": backward-char
"\M-OD": backward-char
"\C-h": backward-delete-char
"\C-?": backward-delete-char
你可以把這個(gè)命令的輸出作為一個(gè)模板,嵌入到 ~/.inputrc 文件。把你喜歡的函數(shù)綁定到方便的按鍵。
其實(shí) readline 有三個(gè)函數(shù)可以讓你方便的查詢函數(shù),變量和宏的綁定情況,它們是:
dump-functions
dump-variables
dump-macros
可是它們?nèi)笔《紱]有被綁定到任何按鍵。你可以為它們分別設(shè)置類似 "C-xf", "C-xv", "C-xm" 這樣容易記憶的綁定。
4.如果忘了綁定……
這樣你就可以設(shè)置你需要的綁定啦!但是你還是有可能在需要的時(shí)候突然記不起哪些鍵綁定可以補(bǔ)全。這時(shí)候你輸入:
$bind -p | grep compl
得到結(jié)果:
"\C-i": complete
"\M-\e": complete
"TAB": complete
"\M-!": complete-command
"\M-/": complete-filename
"\M-@": complete-hostname
"\M-{": complete-into-braces
"\M-~": complete-username
"\M-$": complete-variable
"\M-\C-i": dynamic-complete-history
"\M-g": glob-complete-word
"\M-*": insert-completions
.......
這樣你記不住一個(gè)鍵的時(shí)候就可以方便的查詢,這樣幾次之后,你就會(huì)把自己需要的按鍵都記住了。
配置變量
1.體驗(yàn):
Bash 的 readline 有一些變量可以控制它的行為。比如:
bell-style 可以控制出錯(cuò)時(shí)是 audible(發(fā)出響聲),visible(閃動(dòng)屏幕),還是none(什么都不做);editing-mode 可以控制你是用 Emacs 的輸入方式還是用 vi 的;
completion-query-times 的值控制在補(bǔ)全的個(gè)數(shù)超過多少N時(shí),bash 提示: “Display all N possibilities? (y or n)”;
如果我設(shè)置 expand-tilde 為 on,當(dāng)輸入“l(fā)s ~/doc”,按 TAB 時(shí),命令行會(huì)自動(dòng)變成 "ls /home/wy/doc".
如果把 visible-stats 設(shè)置為 on,那么列出補(bǔ)全的時(shí)候,目錄,可執(zhí)行文件,符號(hào)連接,會(huì)被分別使用 /, *, @ 來標(biāo)記,就像 ls -F 的到的結(jié)果。
2.設(shè)置:
設(shè)置的方法極其簡單,就在 ~/.inputrc 文件里寫入類似語句:
set visible-stats on
然后 "C-x C-r" 使設(shè)置生效。
3.怎樣知道有哪些設(shè)置?
可以設(shè)置的參數(shù)是很多的。使用命令
$bind -v
就可以得到所有這些可以設(shè)置的變量和它們的值了。 |
|