這不是我想要的 shell (2011-05-08)

世上本沒有shell,命令多了,也就成了shell。
——Pope


要說shell,就不能不談起Unix的Keep It Simple Stupid理念。Unix社區崇尚簡潔、專注,鼓勵一個工具只做一件事,做好這件事。當你需要完成一項復雜的工作時,分解,細化,再交給相應的小工具去執行。這樣就需要提供一種機制把各個工具連接起來。所以,在我開來,學習shell重在掌握任務分解和命令間的互聯。

當然,你還會發現,shell的用法很奇怪,畢竟它是個很古老的東西了,包容各種歷史遺留也是無奈之選。


其實,本文是一篇Learning the Bash Shell (3rd)的讀書筆記。

shell是一種用戶與類Unix操作系統之間以文字方式進行交互的媒介。還有其他的交互形式,比如圖形界面。

shell命令一般是祈使句 如:去 給老子 拿瓶水來。

shell命令先是一個動詞,緊接著若干副詞(option)和名詞(argument)(也可能沒有)。

操作的對象大多是文件(Unix里幾乎所有東西都是文件)。文件分為普通文件(文本),可執行文件和目錄。

目錄可以包括若干子目錄,包括本目錄(.)和父目錄(..)。目錄被組織成樹形結構,用路徑來標示。

可以明確指定shell操作的對象的絕對路徑,如果不說就默認是在當前目錄下。當前目錄雖然被稱為目錄卻沒有物理對應,是一個概念上的浮動地址,可以通過pwd(print the working directory,你看多怪的名字,不知道的還以為是password呢)命令來查看,還可以用cd命令(change the working directory)來修改。此外還有主目錄(~)和操作記錄中的上一目錄(-)。

shell的操作對象可以是具體名詞(如某個文件名),也可以是抽象名詞(用來描述某一特征,需要用到通配符(wildcard))。

通配符有三種基本模式:

匹配任一字符、匹配任意字符、匹配字符集。

!, \*, […], [!…], {…}

Unix將I/O設備統一看作文件,并把I/O看作處理任意長的字節流。

Unix把I/O流簡化為標準輸入輸入(standard input)、標準輸出(standard output)和標準錯誤輸出(standard error output)三個端口。輸入流默認為鍵盤,輸出和錯誤流默認為顯示屏。如果需要,可以將這些端口映射到其他設備或文件上(重定向)。

Unix下的小工具往往只專注于某項處理。數據被不同的小工具一道道篩選、加工,最后得到想要的結果。正是因為專注,讓它們更容易組合起來構建復雜的工具。

奇怪的命名

雖然shell命令的命名也不是無章可循,但總歸是很奇怪的。以下是幾個常用的工具:

但比起那些預設變量,這還算好的。

比如位置參數,人家名字直接叫1, 2, ??要想取到它們的值,前面加$($var其實是${var}的簡寫),即$1, $2, ??。還有0(腳本文件的名字)、*(所有位置參數構成的字符串,用IFS(Internal Field Separator)的首字符作分隔符)、@("$1" "$2" ... "$N")、#(位置參數的個數)??

不帶參數的cat就像while true { echo input }

有管道還不夠嗎

cat是用來解釋重定向的絕佳例子: cat < file1 > file2 等價于cp file1 file2command < filename,表示command從某個文件而不是標準輸入拿到數據; command > filename,表示command將數據輸出到某個文件而不是標準輸出。

我覺得這個設計很好,但記法太屎。我寧愿多敲幾個字,把從哪輸入,輸出到哪明確清楚了(比如: file1 > cat > file2)而不是把<>作為前綴貼到操作對象前面。

除了重定向輸出到某個文件,你還可以把輸出作為其他命令的輸入直接導入(管道pipe,用|表示。這個記法也很屎,體現不出方向來,雖然知道是從左到右。為什么不能和重定向統一起來呢?!比如,$ cut -d: -f1 < /etc/passwd | sort | lp寫成/etc/passwd > cut -d: -f1 > sort > lp的形式。可能是于當初把命令設計成前綴形式有關吧,如果當初設計成中綴形式并把命令也看成文件(命令本來就是內存里的一個文件),也許會方便很多)。

文本編輯原來這么陽春白雪

bash的emacs-mode對文本編輯提供很精細的控制:對字符的操作(^B, ^F, ^D, ?)、對單詞的操作(?B, ?F, ?D, ??)、對整句的操作(^A, ^E, ^K, Y(找回前一次被刪掉的東西)),甚至是對歷史記錄的操作(P(相當于↑), ^N(相當于↓), ^R)。

但emacs-mode最強大的功能還得是文本補全(?)。當你敲入幾個字符并按下?,可能會出現四種情況:

  • 沒有以這些字符開頭的詞,shell會小叫一聲beep;
  • 找到一個唯一的匹配,shell會補全它,并附帶一個空格方便你敲其他字符;
  • 如果找到一個唯一匹配的目錄,shell會補全文件名,并附上一個斜杠(/);
  • 如果有多個匹配可能,shell會補上這些可能匹配的最長前綴。

如果你想知道都有哪些可能的選擇,敲兩下?(或者按?-?,它會顯示所有可能選擇)。
shell提供了很多快捷鍵來補全不同類型的名字(比如,?-/ 專門補文件名,?-~專補用戶名,?-!專補命令名??)
既然提到了emacs-mode,不用想也能知道肯定有個vi-mode。

vi最著名的就是用h, j, k, l作為←↓↑→。這得追溯到當初Bill Joy用ADM-3a開發vi,這種機器的h, j, k, l鍵上分別有四個←↓↑→小箭頭,所以后面你知道的。

vi-mode和vi一樣,也有兩種模式(輸入模式和控制模式)。在輸入模式下,你可以鍵入、刪除(?, ^W)。按下 ? 可以進入控制模式。這個模式下,可以用單鍵來控制移動(h, l, b, w, 0, $)(很喜歡這種單鍵控制的方式,其實很多軟件都可以借鑒。如果你不用編輯文字,干嘛要用control、shift這類的輔助鍵。這就好像有名字空間你不用,非得都搞成全家變量一樣)。你不光可以移動一個字符(h, l)、一個單詞(b, w),甚至還可以移動到某個特定的字符上(F-×, f-×,×表示任意字符)按下i(或a, I(等效于0i), A (等效于$a), R (與r略有不同,r只替換一個字符而且不會進入輸入模式,即你不能再鍵入其他字符))切回輸入模式。控制模式下還有個不得不提的命令——撤銷(u, undo)。另外“.”也很有用,它反復執行上一次的操作。
vi也有文本補全,不過不是
?
,而是進入控制模式按反斜杠(/)。

一直覺得vi很有意思,設計很精巧,像一門微型語言。比如刪除操作,按下d(delete)之后不會有什么變化,還要指定刪除的方向(向前還是向后)和長度(字符還是單詞還是整句,是當前光標位置到行首還是到行尾)。這不是v. + adv. + n. 結構么!而且一個動作可以有多個說法(比如刪除整句,可以用dd,也可以用0d$)。讓你感覺它不是一堆互不相干的快捷鍵,而是一句意義明確的指示。

命令行工具一個總的印象就是太費腦子,這里指的是要記的東西太多,不如GUI直觀。但好處就在于它能控制得很精細,不像GUI,界面設計成什么樣就只有哪些功能。

到底0是真是假

在流程控制中,shell用返回狀態作為邏輯判斷的結果。這樣,0(在[...]中)就表示真,其他返回碼均表示假。但在算術表達式($((...))$[...])中,0卻是假,1才是真。而算術式的另一種形式((...))卻用0作為真,1為假

丑陋的語法

如果說if...then...fi是bash的特色的話,bash的case這是巨丑陋:

case expression in
    pattern1 )  
        statements ;;  
    pattern2 )  
        statements ;;   
        ...  
esac

你就不能正常一點?!至少對稱一點,別弄出半邊括號來好不。
還有,按理說shell的語法是不依賴空格或是換行的。可你看看賦值語句,多了空格它不干,再看看[ ... ]少了空格它也不干。而在for, while, select里do如果新起一行就不用打分號。

shell語法看似統一,其實很混亂。這貨不是一門語言,而是一堆微型語言,雖然每個都很簡單,但要想全都記住卻有不小難度。

P.S. Learning the bash Shell似乎沒有繼承Learning系列簡單明了的衣缽,看似很全,其實毫無系統。示例晦澀,講解不清,比如對getopts里OPTSTRING(Mac下好像是這個,書中是OPTARG)的說明,OPTSTRING是一個由option及其所帶參數構成的一個序列,而OPTIND是OPTSTRING里下一個要處理的option的下標(不敢舉例,怕自己理解有誤)。

我想要的shell

首先互聯功能必須很強大;
靈活的語法(不依賴空格神馬的,不限定格式);
統一的語法;

??
(cont.)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容