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

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


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

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


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

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

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

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

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

目錄可以包括若干子目錄,包括本目錄(.)和父目錄(..)。目錄被組織成樹形結(jié)構(gòu),用路徑來標(biāo)示。

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

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

通配符有三種基本模式:

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

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

Unix將I/O設(shè)備統(tǒng)一看作文件,并把I/O看作處理任意長的字節(jié)流。

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

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

奇怪的命名

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

但比起那些預(yù)設(shè)變量,這還算好的。

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

不帶參數(shù)的cat就像while true { echo input }

有管道還不夠嗎

cat是用來解釋重定向的絕佳例子: cat < file1 > file2 等價于cp file1 file2。command < filename,表示command從某個文件而不是標(biāo)準(zhǔn)輸入拿到數(shù)據(jù); command > filename,表示command將數(shù)據(jù)輸出到某個文件而不是標(biāo)準(zhǔn)輸出。

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

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

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

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

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

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

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

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

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

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

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

到底0是真是假

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

丑陋的語法

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

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

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

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

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

我想要的shell

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

??
(cont.)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Ubuntu的發(fā)音 Ubuntu,源于非洲祖魯人和科薩人的語言,發(fā)作 oo-boon-too 的音。了解發(fā)音是有意...
    螢火蟲de夢閱讀 100,673評論 9 468
  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經(jīng)改了很多 但是錯誤還是無法避免 以后資料會慢慢更新 大...
    數(shù)據(jù)革命閱讀 13,236評論 2 33
  • (一)基本命令 命令格式: 命令 參數(shù) 1.ls 顯示文件名,等同于dos下dir命令 命令格式:ls [opti...
    飛羽孟德閱讀 2,078評論 0 3
  • 每天練習(xí)開心就成為開心的人,每天練習(xí)抱怨就成為怨婦。我要每天練習(xí)開心和感恩,大腦就會習(xí)慣感恩和開心的感覺,以后就會...
    熱愛生活的廣佳閱讀 253評論 0 0
  • 如果,我們可以一起看海 時間, 風(fēng), 一片海的聲音。 你曾來過, 但終歸還是相忘江湖。 我止不住的懷念, 慢慢模糊...
    兮十一閱讀 899評論 1 1

友情鏈接更多精彩內(nèi)容