技巧
以下技巧均適用于 bash 弃酌,其他類型的 shell 可能不一定能全部適用引谜。
快捷鍵模式
默認(rèn)情況下型宙, shell 的快捷鍵為 emacs 模式,如: Ctrl-A
/ Ctrl-E
將光標(biāo)移動(dòng)到行 頭 / 尾吝梅, Ctrl-F
/ Ctrl-B
將光標(biāo)向 前 / 后 移動(dòng)一個(gè)字符虱疏, Ctrl-P
/ Ctrl-N
選擇 上 / 下 一條歷史命令等。
為了提升命令編輯效率苏携,我們可以把快捷鍵設(shè)置為 vi 模式做瞪,之后我們就能使用 vi 的快捷鍵來編輯命令, shell 將像 vi 一樣右冻,可以在 normal 模式和 insert 模式之間切換装蓬。
下面的設(shè)置將 shell 的快捷鍵設(shè)置為 vi 模式,并且還附帶了一些輔助設(shè)置:
set -o vi # 將 shell 快捷鍵設(shè)置為 vi 模式
stty werase undef # 取消 Ctrl-W 綁定(向后刪除一個(gè)單詞纱扭,空格為單詞分隔符)
bind '\C-w:backward-kill-word' # 重新綁定 Ctrl-W (向后刪除一個(gè)單詞牍帚,非字母 / 數(shù)字字符為單詞分隔符)
bind '\C-l:clear-screen' # 綁定 Ctrl-L 到清屏功能
bind '\C-f:forward-search-history' # 綁定 Ctrl-F 到向前查找歷史命令功能(Ctrl-S 已綁定到暫停 shell 輸出功能)
定制命令行提示
很多 Linux 的 Server 發(fā)行版的命令行提示默認(rèn)比較簡單,也沒有顏色高亮乳蛾,白(黃 / 綠)花花一片暗赶,我們輸入的命令、命令的輸出同樣也是白(黃 / 綠)花花一片屡久。當(dāng)命令的輸出很多時(shí)忆首,我們用眼睛去識(shí)別哪部分是命令行提示爱榔、輸入的命令或命令的輸出會(huì)很費(fèi)勁被环。
下面的設(shè)置將命令行提示符設(shè)置為:綠色顯示用戶名和主機(jī)名、藍(lán)色顯示當(dāng)前的絕對(duì)路徑详幽、紫色顯示當(dāng)前時(shí)間
PS1='\[\033[01;32m\]\u@\h\[\033[00m\] \[\033[01;34m\]\w\[\033[00m\] \[\033[01;35m\]\t\[\033[00m\] \[\033[01;34m\]\$\[\033[00m\] '
歷史查找
僅使用 上 / 下 方向鍵
(通用)筛欢、k
/ j
( vi 模式)、Ctrl-P
/ Ctrl-N
( emacs 模式)來翻找歷史命令是很低效的唇聘,我們可以對(duì)歷史命令進(jìn)行增量搜索版姑。
按Ctrl-R
之后,輸入要搜索的歷史命令(命令的任何一部分都行迟郎,如命令名剥险、參數(shù)等),這時(shí)將開始?xì)v史命令的向 后 增量搜索過程宪肖。此時(shí)表制,如果連續(xù)按 Ctrl-R
健爬,那么將不斷顯示上一條匹配當(dāng)前輸入的歷史命令。如果有根據(jù) 快捷鍵模式 部分的推薦配置綁定了 Ctrl-F
的話么介,那么按 Ctrl-F
將轉(zhuǎn)為歷史命令的向 前 增量搜索過程娜遵。
找到自己想要的歷史命令后,按 ESC
(vi 模式) / Ctrl-G
(emacs 模式)退出搜索過程壤短,繼續(xù)編輯命令设拟;也可以直接按 Enter
執(zhí)行當(dāng)前命令。
別名
使用命令行難免需要經(jīng)常重復(fù)輸入一些比較繁瑣的命令久脯,給這些繁瑣的命令定義簡單的別名纳胧,可以節(jié)省大量的時(shí)間。別名的另一個(gè)用途是重新定義命令的行為桶现,比如給一些命令增加上默認(rèn)的參數(shù)等躲雅。很多 Linux 發(fā)行版都定義了一些簡單的別名,如下:
alias cp='cp -i'
alias rm='rm -i'
alias mv='mv -i'
這些別名可以防止我們不小心錯(cuò)誤地刪除或覆蓋文件骡和。另外相赁,如果我們想繞過別名機(jī)制,直接使用原始命令慰于,那么在命令前加上反斜杠 \
即可钮科,如下:
\rm test.txt
函數(shù)
有時(shí)候我們可能想使用一條命令執(zhí)行一系列操作,如果我們把這一系列操作定義為別名婆赠,會(huì)導(dǎo)致定義過于復(fù)雜绵脯,可讀性比較差;也可能我們需要傳一些參數(shù)給若干命令休里,使用定義別名的方式無法滿足這一需求蛆挫。這時(shí)候我們可以定義 shell 函數(shù)。下面是幾個(gè)簡單的例子妙黍,其中$1
代表函數(shù)的第一個(gè)參數(shù):
mcd() { mkdir -p "$1" && cd "$1"; }
cls() { cd "$1" && ls; }
backup() { cp "$1"{,.bak}; }
shell 函數(shù)的調(diào)用與執(zhí)行普通命令的方式一樣悴侵,如下:
mcd test
命令補(bǔ)全
我們都知道輸入命令時(shí),可以按 Tab
補(bǔ)全命令拭嫁、文件名等可免,但是可能不是所有人都知道, shell 的補(bǔ)全機(jī)制其實(shí)是設(shè)計(jì)為可擴(kuò)展的做粤。以 debian 系的發(fā)行版為例(其他發(fā)行版可能有出入)浇借,我們能在 /etc
目錄下找到 bash_completion
文件 和 / 或 bash_completion.d
目錄。它們是對(duì)命令補(bǔ)全的擴(kuò)展配置怕品,例如對(duì) git 命令的子命令補(bǔ)全進(jìn)行配置妇垢,這樣我們就能用 Tab
補(bǔ)全 git 的子命令了。在 debian 系發(fā)行版中,安裝 bash-completion
包闯估,我們就能獲得很多常用命令的擴(kuò)展補(bǔ)全配置恢总。
歷史展開
shell 的歷史展開涉及很多內(nèi)容,這里只對(duì)歷史參數(shù)展開方面的部分常用內(nèi)容進(jìn)行敘述睬愤,想做詳細(xì)了解的朋友可以參考History Expansion片仿。
在 shell 命令中,我們可以使用一些特殊的標(biāo)識(shí)來表示 上一條 執(zhí)行過的命令中的某一 個(gè) / 些 參數(shù)尤辱,例如:
-
!*
:所有參數(shù) -
!^
:第一個(gè)參數(shù) -
!$
:最后一個(gè)參數(shù) -
!:n
:第n個(gè)參數(shù) -
!:a-b
:第a個(gè)到第b個(gè)參數(shù)
下面是一個(gè)實(shí)際例子砂豌,我們執(zhí)行以下命令:
ls t1 t2 t3 t4 t5
ls !:2-4
實(shí)際上執(zhí)行的是:
ls t1 t2 t3 t4 t5
ls t2 t3 t4
子進(jìn)程
shell 命令的執(zhí)行默認(rèn)是在當(dāng)前 shell 進(jìn)程中執(zhí)行的,命令的執(zhí)行能影響到當(dāng)前的 shell 環(huán)境光督。如果我們不希望當(dāng)前 shell 環(huán)境被影響阳距,那么我們可以顯式地指定命令在子進(jìn)程中執(zhí)行,方法就是用 小括號(hào)
將整條命令括起來结借,例如:
(cd build && cmake ..)
命令執(zhí)行完成后筐摘, shell 的當(dāng)前路徑并不會(huì)發(fā)生變化。
子進(jìn)程的創(chuàng)建還有另外一種應(yīng)用場景船老,即把一條命令的輸出作為另外一條命令的 參數(shù) 咖熟。這里與管道不一樣,管道是將一條命令的輸出作為另外一條命令的 輸入 柳畔。例如馍管,我們可以執(zhí)行以下命令來遞歸統(tǒng)計(jì)當(dāng)前目錄下,所有Go源文件的代碼行總數(shù):
cat $(find -name "*.go") | wc -l
或:
cat `find -name "*.go"` | wc -l
工具
tmux
tmux 是終端復(fù)用工具薪韩,簡單地說确沸,就是我們能用它在終端上創(chuàng)建多個(gè) 窗口缨恒,窗口之間可以通過快捷鍵快速切換妓蛮。同時(shí)援岩,每個(gè)窗口又可以任意分割成多個(gè) 窗格有勾,光標(biāo)可以通過快捷鍵在窗格之間快速跳轉(zhuǎn)。
tmux 的基本使用方法在網(wǎng)上有很多資料可以參考蛙吏,這里就不贅述了帖池。這里只敘述它的一些常規(guī)功能之外的優(yōu)點(diǎn)年扩,如下:
- CS (Client-Server) 設(shè)計(jì)架構(gòu)盾剩,我們可以與 Server 建立起多個(gè)會(huì)話雷激,每個(gè)會(huì)話可以獨(dú)立管理窗口替蔬。我們可以隨時(shí)斷開會(huì)話告私,然后關(guān)閉終端窗口,只要 Server 進(jìn)程還在承桥,我們就可以隨時(shí)重建會(huì)話驻粟,會(huì)話中的窗口和其中運(yùn)行的進(jìn)程完全不會(huì)受影響。
- 得益于 CS 架構(gòu),多個(gè) Client 可以通過網(wǎng)絡(luò)蜀撑,與同一個(gè) Server 的同一個(gè)會(huì)話建立連接挤巡, Server 的會(huì)話狀態(tài)將實(shí)時(shí)推送到所有參與會(huì)話的 Client,也就是說酷麦,這是在做 直播矿卑,某一個(gè) Client 的操作將對(duì)其他 Client 實(shí)時(shí)可見。
- 還是得益于 CS 架構(gòu)沃饶,再加上 tmux 對(duì)子命令的支持母廷,我們可以通過 tmux 子命令與 Server 交互。這樣糊肤,我們就可以把常用的 tmux 操作寫成 shell 腳本琴昆,執(zhí)行自動(dòng)化操作。
下面是一段 tmux 配置馆揉,可以加入到 ~/.tmux.conf
文件中业舍,作用是將當(dāng)前窗口分割成 田 字形的四個(gè)窗格,綁定的快捷鍵為 前綴鍵(默認(rèn)Ctrl-B) Shift-W
:
bind-key W split-window -h \; split-window \; select-pane -t 0 \;\
split-window \; select-pane -t 0
下面是一段 shell 腳本升酣,作用是創(chuàng)建一個(gè) tmux 會(huì)話舷暮,然后在該會(huì)話中創(chuàng)建編號(hào)為 0 - 9 的十個(gè)窗口,最后連接上該會(huì)話噩茄。腳本接受一個(gè)可選參數(shù)脚牍,如果該參數(shù)不為空,那么將作為會(huì)話的名字巢墅,否則诸狭,會(huì)話名字默認(rèn)為 “0”。腳本執(zhí)行時(shí)君纫,需要確保當(dāng)前沒有連接 tmux 會(huì)話:
#!/bin/bash
if [ -z $1 ]; then
SESSION_NAME="0"
else
SESSION_NAME=$1
fi
if $(tmux has-session -t "${SESSION_NAME}" > /dev/null 2>&1); then
tmux attach-session -t "${SESSION_NAME}"
exit 0
fi
tmux new-session -d -s "${SESSION_NAME}"
for i in {1..9}
do
tmux new-window
done
tmux select-window -t "${SESSION_NAME}:0"
tmux attach-session -t "${SESSION_NAME}"