bash 程式設計指南(轉)

BSDLite發表於2007-08-11
bash 程式設計指南(轉)[@more@]  什麼是shell
  Linux上最常見的shell
  命令補齊(Command-line completion)和通配
  命令歷史記錄(Command history)和別名
  重定向和管道
  改變提示符
  程式控制(Job control)
  如何使用者化配置你的bash shell

  另外你還將看到一些最常用的bash命令和記憶體變數的用法,讀完本文後你將能更快和更有效地使用bash。 Shells in a Nutshell

  什麼是shell?總之這個詞好象總是出現在 Linux 裡,但很多新使用者並不清楚它的明確的含義。本節將給出一個確切的解釋並說明為什麼在Linux中它顯得如此的重要。

  什麼是Shell?
  shell是你(使用者)和Linux(或者更準確的說,是你和Linux核心)之間的介面程式。你在提示符下輸入的每個命令都由shell先解釋然後傳給Linux核心。

  -----------------------------------------------------------------
  注意: 如果你熟悉m$-dos,你將認出這很象DOS 使用者和 COMMAND.COM之間的關係。唯一的區別是command.com 的功能遠不能和shell 相提並論。
  -----------------------------------------------------------------

  shell 是一個命令語言直譯器(command-language interpreter)。擁有自己內建的 shell 命令集。此外,shell也能被系統中其他有效的Linux 實用程式和應用程式(utilities and application programs)所呼叫。

  不論何時你鍵入一個命令,它都被Linux shell所解釋。一些命令,比如列印當前工作目錄命令(pwd),是包含在Linux bash內部的(就象DOS的內部命令)。其他命令,比如複製命令(cp)和移動命令(rm),是存在於檔案系統中某個目錄下的單獨的程式。而對使用者來說,你不知道(或者可能不關心)一個命令是建立在shell內部還是一個單獨的程式。

  shell 首先檢查命令是否是內部命令,不是的話再檢查是否是一個應用程式,這裡的應用程式可以是Linux本身的實用程式,比如ls 和 rm,也可以是購買的商業程式,比如 xv,或者是公用軟體(public domain software),就象 ghostview。然後shell試著在搜尋路徑裡尋找這些應用程式。搜尋路徑是一個能找到可執行程式的目錄列表。如果你鍵入的命令不是一個內部命令並且在路徑裡沒有找到這個可執行檔案,將會顯示一條錯誤資訊。而如果命令被成功的找到的話,shell的內部命令或應用程式將被分解為系統呼叫並傳給Linux核心。

  shell的另一個重要特性是它自身就是一個解釋型的程式設計語言,shell 程式設計語言支援在高階語言裡所能見到的絕大多數程式控制結構,比如迴圈,函式,變數和陣列。shell 程式語言很易學,並且一旦掌握後它將成為你的得力工具。任何在提示符下能鍵入的命令也能放到一個可執行的shell程式裡,這意味著用shell語言能簡單地重複執行某一任務。

  shell 如何啟動
  shell在你成功地登入進入系統後啟動,並始終作為你與系統核心的互動手段直至你退出系統。你係統上的每位使用者都有一個預設的shell。

  每個使用者的預設shell在系統裡的passwd檔案裡被指定,該檔案的路徑是/etc/passwd。passwd檔案裡還包含有其他東西:每個人的使用者ID號,一個口令加密後的複製和使用者登入後立即執行的程式,(注:為了加強安全性,現在的系統一般都把加密的口令放在另一個檔案--shadow中,而passwd中存放口令的部分以一個x字元代替)雖然沒有嚴格規定這個程式必須是某個Linux shell,但大多數情況下都如此。

  最常用的shell
  在Linux 和 UNIX系統裡可以使用多種不同的shell可以使用。最常用的幾種是 Bourne shell (sh), C shell (csh), 和 Korn shell (ksh)。三種shell 都有它們的優點和缺點。Bourne shell 的作者是 Steven Bourne。它是 UNIX 最初使用的shell 並且在每種 UNIX 上都可以使用。Bourne shell 在 shell 程式設計方面相當優秀,但在處理與使用者的互動方面作得不如其他幾種 shell。

  C shell 由 Bill Joy 所寫,它更多的考慮了使用者介面的友好性。它支援象命令補齊(command-line completion)等一些 Bourne shell 所不支援的特性。普遍認為C shell 的程式設計介面做的不如 Bourne shell, 但 C shell 被很多 C程式設計師使用因為 C shell的語法和 C語言的很相似,這也是C shell名稱的由來。

  Korn shell (ksh) 由 Dave Korn 所寫。它集合了C shell 和 Bourne shell 的優點並且和 Bourne shell 完全相容。

  除了這些 shell 以外,許多其他的 shell 程式吸收了這些原來的 shell 程式的優點而成為新的 shell 。在 Linux 上常見的有 tcsh (csh 的擴充套件),Bourne Again shell(bash, sh 的擴充套件), 和Public Domain Korn shell (pdksh, ksh 的擴充套件)。bash 是大多數Linux 系統的預設 shell。

  The Bourne Again Shell
  Bourne Again shell (bash), 正如它的名字所暗示的,是 Bourne shell 的擴充套件。bash 與 Bourne shell 完全向後相容,並且在 Bourne shell 的基礎上增加和增強了很多特性。bash 也包含了很多 C 和 Korn shell 裡的優點。bash 有很靈活和強大的程式設計介面,同時又有很友好的使用者介面。

  為什麼要用 bash 來代替 sh 呢?Bourne shell 最大的缺點在於它處理使用者的輸入方面。在 Bourne shell 裡鍵入命令會很麻煩,尤其當你鍵入很多相似的命令時。而 bash 準備了幾種特性使命令的輸入變得更容易。

  命令補齊(Command-Line Completion)
  通常你在 bash (或任何其他的 shell)下輸入命令時你不必把命令輸全 shell 就能判斷出你所要輸入的命令。例如,假定當前的工作目錄包含以下的檔案和子目錄:

News/ bin/ games/ mail/ samplefile test/

  如果你要進入 test 子目錄,你將會輸入以下的命令:

cd test

  這個命令能夠滿足你的需要,但 bash還提供了稍微不同的方法來完成同樣的事。因為 test 是當前目錄裡唯一以字母 t開頭的子目錄,bash在你只輸入字母 t後就能判斷出你要做什麼了:

cd t

  在你鍵入那個字母后,唯一的可能就是 test 。想讓 bash 幫你結束命令的話,按下 Tab 鍵:

cd t

  當你這樣做以後,bash 將幫你補齊命令並顯示在螢幕上。但在你按下Enter鍵以前命令並沒有被執行,bash 會讓你檢驗補齊的命令是否是你真正需要的。在輸入象這樣短的命令時你也許看不出它的價值所在,甚至在命令很短時還會簡慢輸入的速度,但是當你要輸入的命令有點長時,你會發現這個特性是多麼的美好。
  但是當目錄裡有不止一個以字母 t 開頭的檔案時會發生什麼情況呢?在你使用命令補齊時會有問題,讓我們看看下面的情況,當前目錄裡有下列內容:

News/bin/ mail/samplefile test/tools/ working/

  現在這個目錄裡有兩個以字母 t 開頭的檔案。假設你仍然想進入 test 子目錄,如何使用命令補齊呢?如果你象先前那樣鍵入:

cd t

  bash 將不知道你到底想進入哪個子目錄,因為給出的資訊並不唯一。如果你這樣做了的話,bash 將發出一聲蜂鳴提醒你沒有足夠的資訊來補齊你的命令。蜂鳴之後bash 並不改變輸入的命令,這將使你能在原來的基礎上再輸入更多的資訊,在這個例子中你僅需再鍵入一個 e 並再按一下 Tab 鍵,這時 bash 就有足夠的資訊來完成你的命令了:

cd test

  當你輸入命令時不論何時按下 Tab 鍵,bash 都將盡其所能地試圖補齊命令,不行的話會發出蜂鳴來提醒你需要更多的資訊。你需要鍵入更多的字元,並再次按下 Tab 鍵,重複這個過程直至你期望的命令出現。

  萬用字元
  另一個使命令輸入變得更簡單的方法是在命令中使用萬用字元。bash 支援三種萬用字元:
  *匹配任何字元和任何數目的字元
  ?匹配任何單字元
  [...]匹配任何包含在括號裡的單字元
  * 萬用字元的使用有些象命令補齊。例如,假設當前目錄包含以下檔案:

News/bin/ games/ mail/samplefile test/

  如果你想進入 test 目錄,你將鍵入 cd test, 或者你想用命令補齊:

cd t

  現在有第三種方法來做同樣的事。因為僅有一個檔案以字母 t 開頭,你也能用
  * 萬用字元來進入該目錄。鍵入下列命令:

cd t*

  * 匹配任何字元和任何數目的字元,所以 shell 將把 t* 替換為 test(當前目錄裡唯一和通配方案匹配的檔案)。當前目錄裡只有一個檔案以字母 t 開頭的話這將是可靠的。但是如果當前目錄裡有不止一個檔案以字母 t 開頭,shell 將試著進入第一個符合匹配方案的目錄,這個目錄是以字母表排序的第一個目錄,這個目錄也許是也許不是你所期望的。
  萬用字元 * 的一個更實際的用途是通配你要執行的命令中的多個名字相似的檔案。例如,假設當前目錄裡包含以下檔案:

ch1.doc ch2.doc ch3.docchimpconfigmail/test/tools/

  如果你需要列印所有副檔名是 .doc 的檔案,你能使用象這樣簡化的命令:

lpr *.doc

  在這個例子中,bash 將把 *.doc 替換為當前目錄下所有檔名符合通配方案的檔案。在 bash 進行了替換後,該命令將被處理為:

lpr ch1.doc ch2.doc ch3.doc

  lpr 命令將以ch1.doc, ch2.doc, 和 ch3.doc為引數被呼叫。
  ----------------------------------------------------------------
  注意: 除了以上給出的例子外,還有幾種方法:

lpr *doc
lpr *oc
lpr *c

  ----------------------------------------------------------------
  萬用字元 ? 除了只能匹配單個字元外,其他功能都與萬用字元 *相同,如果用萬用字元 ? 來列印前面提到的那個目錄裡所有副檔名是 .doc 的檔案的話,鍵入下面的命令:

lpr ch?.doc

  萬用字元[...]能匹配括號中給出的字元或字元範圍。同樣以前面的目錄為例,列印那個目錄裡所有副檔名是 .doc 的檔案,你可以鍵入下列命令之一:

lpr ch[123].doc

  或者:

lpr ch[1-3].doc 命令歷史記錄

  bash 也支援命令歷史記錄。這意味著 bash 保留了一定數目的你先前已經在shell 裡輸入過的命令。這個數目取決於一個叫做HISTSIZE的變數。有關 HISTSIZE 的更多資訊,請看本文後面的“bash 變數”一節。

  bash 把你先前輸入的命令文字儲存在一個歷史列表中。當你用你的帳號登入後歷史列表將根據一個歷史檔案被初始化。歷史檔案的檔名被一個叫 HISTFILE 的 bash變數指定。歷史檔案的預設名字是 .bash_history。這個檔案通常在你的使用者目錄中。(注意該檔案的檔名以一個句號開頭,這意味著它是隱含的,僅當你帶 -a 或 -A引數的 ls 命令列目錄時才可見)

  僅將先前的命令存在歷史檔案裡是沒有用的,所以 bash 提供了幾種方法來呼叫它們。使用歷史記錄列表最簡單的方法是用上方向鍵。按下上方向鍵後最後鍵入的命令將出現在命令列上。再按一下則倒數第二條命令會出現,以此類推。如果上翻多了的話也可以用向下的方向鍵來下翻。(和 DOS 實用程式doskey一樣)如果需要的話,顯示在命令列上的歷史命令可以被編輯。

  另一個使用命令歷史檔案的方法是用 bash 的內部命令 history 和 fc(fix 命令)命令來顯示和編輯歷史命令。history 命令能以兩種不同的方法來呼叫。第一種是:

history [n]

  當 history 命令沒有引數時,整個歷史命令列表的內容將被顯示出來。下面是一個命令歷史列表的例子:

1mkdir /usr/games/pool
2cp XpoolTable-1.2.linux.tar.z /usr/games/pool
3cd /usr/games/pool/
4ls
5gunzip XpoolTable-1.2.linux.tar.z
6tar -xf XpoolTable-1.2.linux.tar
7ls
8cd Xpool
9ls
10xinit
11exit
12which zip
13zip
14more readme
15vi readme
16exit

  使用 n 引數的作用是僅有最後 n 個歷史命令會被列出。例如,history 5 顯示最後 5 個命令。
  呼叫 history 命令的第二種方法用於修改命令歷史列表檔案的內容。命令的語法如下:

history [-r|w|a|n] [filename]

  這種形式中,-r 選項告訴 history 命令讀命令歷史列表檔案的內容並且把它們當作當前的命令歷史列表。-w 選項將把當前的命令歷史記錄寫入檔案中並覆蓋檔案原來的內容。-a 選項把當前的命令歷史記錄追加到檔案中。-n 選項將讀取檔案中的內容並加入到當前歷史命令列表中。如果 filename 選項沒有被指定,history 命令將用變數HISTFILE 的值來代替。
  fc 命令能用兩種方法來編輯歷史命令。第一種使用下列語法:

fc [-e editor_name] [-n] [-l] [-r] [first] [last]

  這裡所有引數都是可選的。-e editor_name 選項用來指定用於編輯命令的文字編輯器。 first 和 last 選項用於選擇列出歷史命令的範圍,既可以是數字也可以是字串。-n 選項禁止列出命令的編號。-r 選項反向列出匹配的命令。-l 選項把匹配的命令列列在螢幕上(而不是在編輯器中)。如果-e editor_name引數沒有被指定,則以變數FCEDIT的值來代替,如果該變數不存在的話,則用變數EDITOR的值來代替,都不存在的話將使用vi編輯器。

  別名
  bash 的另一個使你的工作變得輕鬆的方法是命令別名。命令別名通常是其他命令的縮寫,用來減少鍵盤輸入。例如,你經常要鍵入如下的命令,你也許會傾向於為它建立一個別名來減少工作量:

cd /usr/X11/lib/X11/fvwm/sample-configs

  假如為這個長命令建立一個名為goconfig的別名,在bash提示符下鍵入如下命令:

alias goconfig='cd /usr/X11/lib/X11/fvwm/sample-configs'

  現在,除非你退出bash,鍵入goconfig將和原來的長命令有同樣的作用。如果想取消別名,可以使用下面的命令:

unalias goconfig

  這是一些很多使用者認為有用的別名,你可以把它們寫入你的.profile檔案中提高工作效 :

alias ll='ls -l'
alias log='logout'
alias ls='ls -F'

  如果你是一名DOS使用者並且習慣了DOS命令,你能下面的別名定義使你的 Linux 表現得象DOS 一樣:

alias dir='ls'
alias copy='cp'
alias rename='mv'
alias md='mkdir'
alias rd='rmdir'

  -------------------------------------------------------------
  注意: 在定義別名時,等號的兩頭不能有空格,否則 shell 不能決定你需要做什麼。僅在你的命令中包含有空格或特殊字元時才需要引號。
  -------------------------------------------------------------
  如果你鍵入不帶任何引數的alias命令,將顯示所有已定義的別名,例如:

alias dir='ls'
alias ll='ls -l'
alias ls='ls -F'
alias md='mkdir'
alias net='term /dev/modem 2> /dev/null&'

  alias rd='rmdir' 輸入重定向輸入重定向用於改變一個命令的輸入源。一些命令需要在命令列裡輸入足夠的資訊才能工作。比如 rm,你必須在命令列裡告訴 rm 它你要刪除的檔案。另一些命令則需要更詳細的輸入,這些命令的輸入可能是一個檔案。比如命令 wc 統計輸入給它的檔案裡的檔案裡的字元數,單詞數和行數。如果你僅在命令列上鍵入 wc ,wc 將等待你告訴它要統計什麼,這時 bash 就好象死了一樣,你鍵入的每樣東西都出現在螢幕上,但什麼事也不會發生。這是因為 wc 命令正在為自己收集輸入。如果你按下Ctrl-D,wc 命令的結果將被寫在螢幕上。如果你輸入一個檔名做引數,象下面的例子一樣,wc 將返回檔案所包含的字元數,單詞數,和行數:

wc test
11 2 1

  另一種把test檔案內容傳給 wc 命令的方法是重定向 wc 的輸入。

wc
  輸入重定向並不經常使用因為大多數命令都以引數的形式在命令列上指定輸入檔案的檔名。儘管如此,當你使用一個不接受檔名為輸入引數的命令,而需要的輸入又是在一個已存在的檔案裡時,你就能用輸入重定向解決問題。

  輸出重定向
  輸出重定向比輸入重定向更常用。輸出重定向使你能把一個命令的輸出重定向到一個檔案裡,而不是顯示在螢幕上。

  很多情況下都可以使用這種功能。例如,如果某個命令的輸出很多,在螢幕上不能完全顯示,你能把它重定向到一個檔案中,稍後再用文字編輯器來開啟這個檔案;當你想儲存一個命令的輸出時也可以使用這種方法。還有,輸出重定向可以用於把一個命令的輸出當作另一個命令的輸入時。(還有一種更簡單的方法可以把一個命令的輸出當作另一個命令的輸入,就是使用管道,管道的使用將在本文的“管道”一節介紹)

  輸出重定向的使用與輸入重定向很相似,但是輸出重定向的符號是 > 。
  ------------------------------------------------------------
  注意:記憶輸入/輸出重定向符號的最好方法是把 當作一個大口指向有輸出的命令的漏斗。
  ------------------------------------------------------------
  重定向舉例,當你要把 ls 命令的輸出儲存為一個名為 directory.out 的檔案時,你可以使用下面的命令:

ls > directory.out


  管道
  管道可以把一系列命令連線起來。這意味著第一個命令的輸出會透過管道傳給第二個命令而作為第二個命令的輸入,第二個命令的輸出又會作為第三個命令的輸入 ,以此類推。而管道行中最後一個命令的輸出才會顯示在螢幕上(如果命令列裡使用了輸出重定向的話,將會放進一個檔案裡)。
  你能透過使用管道符 | 來建立一個管道行,下面的示例就是一個管道行:

cat sample.text | grep "High" | wc -l

  這個管道將把 cat 命令(列出一個檔案的內容)的輸出送給grep命令。grep 命令在輸入裡查詢單詞 High,grep命令的輸出則是所有包含單詞 High的行,這個輸出又被送給 wc命令。帶 -l選項的 wc命令將統計輸入裡的行數。假設 sample.txt的內容如下:

Things to do today:
Low: Go grocery shopping
High: Return movie
High: Clear level 3 in Alien vs. Predator
Medium: Pick up clothes from dry cleaner

  管道行將返回結果 2,指出你今天有兩件很重要的事要做:

cat sample.text | grep "High" | wc -l
2

提示符
  bash 有兩級使用者提示符。第一級是你經常看到的 bash 在等待命令輸入時的提示符。預設的一級提示符是字元$(如果是超級使用者,則是#號)。你可以透過改變bash 的PS1變數的值來改變你的預設提示符

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

相關文章