Sobell談bash和Linux命令列命運(轉)

BSDLite發表於2007-08-11
Sobell談bash和Linux命令列命運(轉)[@more@]《Linux命令、編輯器和外殼程式設計實踐指南》一書的作者Mark G. Sobell在接受LinuxPlanet欄目採訪時談了他本人對Linux命令列命運的看法。


  LinuxPlanet(以下簡稱LP):命令列死亡了嗎?

  答:不,根本就沒有死亡。對於某些人和執行某些任務來說,使用圖形介面更容易和更簡潔。這實際上依賴於你要做什麼和你是誰。圖形使用者介面和命令列之間的區別就像自動變檔與變速桿一樣。我使用變速桿是因為它能夠讓我更好地控制汽車,讓我更多地感覺到汽車在做什麼以及汽車是如何做到的。

  當然,這個討論假設你是以系統管理員的級別操作檔案的。有些應用程式有使用者圖形介面,有些應用程式也許沒有這種介面,或者只有非常原始的命令列介面。設法從命令列執行這些應用程式是沒有意義的。

  對命令列有好處的一件事情是它能夠讓你訪問數百個工具軟體。在命令列上面,你可以使用一個管道把工具軟體結合在一起執行一項單個工具軟體無法完成的工作。下面是從我的“Linux命令、編輯器和外殼程式設計實踐指南”一書中摘錄的部分內容,談了有關這些管道及其連線的過程:

  “一個過程是Linux執行一個命令。過程之間的通訊是UNIX/Linux的驗證證明之一。一個通道(書寫為垂直的直線“|”,在命令列中或者鍵盤上是一個垂直的實線)提供了這種通訊最簡單的方式。簡單地說,一個通道接受一個工具軟體的輸出,然後把那個輸出輸入到其它工具軟體。使用UNIX/Linux的詞彙,這個通道接受了一個過程的標準輸出,並把這個標準的輸出作為另一個過程的標準輸入。一個過程在螢幕上顯示的大多數內容將傳送給標準的輸出。如果你沒有重新定向這個輸出,這個輸出就在螢幕上顯示出來。使用一個通道,你可以重新定向這個輸出,這樣它就變成了另一個工具軟體的標準的輸入。”

  例如,你可以把列出目錄中檔案的命令“ls”與計算一個目錄中的檔案和字數的命令“wc -w”結合在一起使用:

  $ ls | wc -w

  45

  在Linux系統管理領域,使用者圖形介面通常是建在命令列工具之外的,因此,你不能得到使用者圖形介面工具的好處。當然,除非你能使用滑鼠。你在命令列下面能夠完成的工作在圖形使用者介面系統管理工具中經常無法完成。

  Bourne和Bourne外殼程式

  LP:你能討論一下bash(Bourne Again Shell)並且解釋一下它與原來的Bourne外殼程式有什麼區別嗎?

  答:這個外殼程式(shell)是命令列的解釋程式,它分析你輸入的命令列並且呼叫你申請的程式,並且把你在命令列中輸入的引數傳遞給這個程式。這個外殼程式也是一種高階的程式語言。bash是許多Linux系統預設的外殼程式。大多數Linux釋出版軟體還包含其它的外殼程式,甚至還有更多的外殼程式可供下載。

  由GNU計劃編寫的bash包含了原始版本的Bourne外殼程式,那是AT&T公司釋出的UNIX下面的第一個外殼程式。我曾經建議讀者考慮使用C外殼程式作為他們的互動式外殼程式,因為它擁有原始版本的Bourne外殼程式所沒有的一些重要功能。目前,bash擁有所有這些功能,而且某些bash還包括命令完成、歷史(這樣你可以編輯和重複以前的命令)和工作控制(允許你在前端和後端之間轉移工作)等功能。當然,你可以使用bash編寫外殼程式指令碼(批處理檔案)。

  許多Linux系統外殼程式指令碼是從“#!/bin/sh”開始的。這一行命令讓指令碼在外殼程式下執行。這個外殼程式不是Bourne外殼程式的一部分,而是一個指向bash的連結。

  由於具有長期的和成功的歷史,原始的Bourne外殼程式一直用來編寫許多幫助管理Unix系統的外殼指令碼。其中有些在Linux中出現的指令碼稱作bash指令碼。雖然bash指令碼包含了許多原始的Bourne外殼程式中所沒有的擴充套件功能和特性,但是,bash保持了對原始的Bourne外殼程式的相容,因此你可以在bash下面執行Bourne外殼指令碼。原始的Bourne外殼程式在Unix系統中稱作sh。在Linux系統中,sh是指向bash的一個符號連結,以確保需要Bourne外殼程式的指令碼能夠執行。當被稱作sh的時候,bash盡最大的努力效仿原始的Bourne外殼程式。

  LP:你會建議Linux的新手學習bash還是學習TC外殼程式?

  答:如果你是一個頑固的C語言外殼程式設計師,你可以繼續使用TC外殼程式(tcsh)。否則,我建議你使用bash。幾乎所有的控制Linux的管理外殼指令碼程式都是由bash執行的。因此,如果你學習bash,你將能夠很容易地理解和修改這些指令碼。

  awk

  LP:你為什麼使用awk?

  答:這是一個很好的問題,特別是在很多人直接使用Perl語言的時候。這個工具軟體簡單而功能強大。在Perl出現之前,awk一直是操作檔案的工具之一。目前,awk仍是有用的。GNU版本的awk稱作gawk,有一些新的功能,使其成為一個非常有用的工具。下面是我的書中討論的有關如何讓gawk與協作程式之間相互通訊的部分內容:

  協作程式:雙向I/O

  協作程式是與另一個程式並行執行的一個程式。從3.1版本開始,gawk能夠啟動一個協作程式直接與後臺程式交換資訊。當你在客戶機/伺服器環境中工作,設定一個SQL前端和後端或者在一個網路上與一個遠端系統交換資料的時候,協作程式是很有用的。gawk句法透過在啟動後臺程式的程式名稱前面新增一個運算子號“|&”來識別一個協助程式。

  一個協助程式指令必須是一個過濾器(也就是說,它讀取標準的輸入並且寫入標準的輸出),必須在完成一行輸出之後就進行重新整理,而不是積累很多行很以後再進行輸出。當一個指令作為協作程式被啟動之後,它將透過一個雙向的通道與一個gawk程式連線,這樣,你就可以對這個協作程式進行讀寫操作。

  當與tr工具一起使用時,這個工具在完成每一行指令之後不重新整理其輸出。這個“to_upper”外殼指令碼是不重新整理其輸出的tr指令的外殼。這個過濾器可以作為協作程式執行。對於讀取的每一行指令,“to_upper”寫入這些行,並且把這些行翻譯成大寫字母和標準的輸出。如果你要“to_upper”顯示除錯的輸出,可刪除“set -x”前面的“#”。

  $ cat to_upper

  #!/bin/bash

  #set -x

  while read arg

  do

  echo "$arg" | tr '[a-z]' '[A-Z]'

  done

  $ echo abcdef | to_upper

  ABCDEF

  g6程式啟動“to_upper”作為一個協作程式。這個gawk程式讀取標準的輸入或者在命令列中指定的一個檔案,把這個輸入翻譯成大寫字母,並把翻譯的資料寫入一個標準的輸出。

  $ cat g6

  {

  print $0 |& "to_upper"

  "to_upper" |& getline hold

  print hold

  }

  $ gawk -f g6 < alpha

  AAAAAAAAA

  BBBBBBBBB

  CCCCCCCCC

  DDDDDDDDD

  這個g6程式在括號之內有一個混合的指令,包含三個指令。由於沒有執行方式,gawk對於每一行輸入內容都執行一次這個混合的指令。

  第一個指令“print $0”把當前的記錄傳送到標準的輸出。“|&”運算子把標準的輸出從新指向名為“to_upper”的程式。“to_upper”作為一個協作程式在執行。這些程式的外邊需要一個括號。第二個指令把來自“to_upper”的標準輸出重新指向一個“getline”指令。這個指令將其標準的輸出複製到這個名為“hold”的變數。第三個指令“print hold”把“hold”變數的這個內容傳送到標準的輸出。

  這個工具的名稱是“tr”

  LP:你能不能更多地談一下“tr”工具?

  答:哦,tr,好的。首先想到的事情是這是一個微不足道的問題的答案。命名一個Linux工具。這個工具僅接收來自標準輸入的輸入,從來不接收作為來自命令列變數的檔案的輸入。這個怪物只是有時候有用,但是,當它有用的時候,它是非常有用的。下面是摘錄一些有關“tr”的內容:

  tr工具讀取標準輸入中每一個輸入的字元,把字元映象為一個替代的字元並刪除原來的字元或者把不再管那個字元。這個工具讀取標準的輸入並且寫入標準的輸出。

  tr工具一般與兩個引數一起使用,string1(字串1)和string2(字串2)。每個字元在這兩個字串中的位置是非常重要的:每一次tr發現在其輸入的string1中的一個字元的時候,它都要用string2中相對應的字元取代那個字元。

  使用一個引數,string1和“--delete”(刪除指令)的選項,tr刪除在string1中指定的字元。這個“squeeze-repeats ”(縮減連續重複的字元)選項使用一個出現的字元取代在string1中連續出現的字元,例如abbc將變成abc。

  你可以使用一個連字元代表在instring1或者string2中的一系列字元。這兩個命令列在下面的例子中產生同樣的結果:

  $ echo abcdef | tr 'abcdef' 'xyzabc'

  xyzabc

  $ echo abcdef | tr 'a-f' 'x-za-c'

  xyzabc

  下面這個例子演示了隱藏文字的流行的做法。這個方法通常稱作“ROT13”(rotate 13),因為它用第十三個字母代替第一個字母,用第十四個字母代替第二個字母,以此類推。

  $ echo The punchline of the joke is ... |

  > tr 'A-M N-Z a-m n-z' 'N-Z A-M n-z a-m'

  Gur chapuyvar bs gur wbxr vf ...

  為了使這個文字再次智慧化,把給tr的引數順序倒過來:

  $ echo Gur chapuyvar bs gur wbxr vf ... |

  > tr 'N-Z A-M n-z a-m' 'A-M N-Z a-m n-z'

  The punchline of the joke is ...

  這個“--delete”選項使tr刪除選擇的字元:

  $ echo If you can read this, you can spot the missing vowels! |

  > tr --delete 'aeiou'

  If y cn rd ths, y cn spt th mssng vwls!

  在下面的例子中,tr替換幾個字元並且產生與單個字元相同的一對兒字元:$ echo tennessee | tr --squeeze-repeats 'tnse' 'srne'

  serene

  下一個例子用一個“新檔案”字元替換在draft1檔案中的沒有按照字母順序排列的每一個字元。輸出是一個詞彙列表,每一行一個單詞:

  $ tr --complement --squeeze-repeats '[:alpha:]' ' ' < draft1

  最後一個例子是使用字元類提升那裡的字串“hi there”:

  $ echo hi there | tr '[:lower:]' '[:upper:]'

  HI THERE

  總結

  LP:最後還有什麼想法嗎?

  答:我想說命令列並不適用於每一個人。命令列適用於那些要求親手操作和對他們馴服的野獸有更強的控制力的那些使用者。學習外殼程式能夠做什麼已經成功了一半。成功的另一半是學習一些與Linux釋出版一起推出的許多工具的知識。你不需要了解每一個指令的每一個引數。瞭解每一個指令名稱的含義和每個指令基本上能做什麼就足夠了。你可以閱讀我的書中有關人和資訊的內容或者有關指令參考的部分。檢視tac工具並且在一開始的時候會對這個工具名稱的起源感到可笑。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617542/viewspace-947274/,如需轉載,請註明出處,否則將追究法律責任。

相關文章