shell程式設計入門
從程式設計師的角度來看,Shell本身是一種用C語言編寫的程式,從使用者的角度來看,Shell是使用者與Linux作業系統溝通的橋樑。使用者既可以輸入命令執行,又可以利用Shell指令碼程式設計,完成更加複雜的操作。在LinuxGUI日益完善的今天,在系統管理等領域,Shell程式設計仍然起著不可忽視的作用。深入地瞭解和熟練地掌握Shell程式設計,是每一個Linux使用者的必修功課之一。
Linux的Shell種類眾多,常見的有:BourneShell(/usr/bin/sh或/bin/sh)、Bourne Again Shell(/bin/bash)、CShell(/usr/bin/csh)、K Shell(/usr/bin/ksh)、Shell forRoot(/sbin/sh),等等。不同的Shell語言的語法有所不同,所以不能交換使用。每種Shell都有其特色之處,基本上,掌握其中任何一種就足夠了。在本文中,我們關注的重點是Bash,也就是Bourne AgainShell,由於易用和免費,Bash在日常工作中被廣泛使用;同時,Bash也是大多數Linux系統預設的Shell。在一般情況下,人們並不區分Bourne Shell和Bourne AgainShell,所以,在下面的文字中,我們可以看到#!/bin/sh,它同樣也可以改為#!/bin/bash。
利用vi等文字編輯器編寫Shell指令碼的格式是固定的,如下:
#!/bin/sh
#comments
Your commands go here
首行中的符號#!告訴系統其後路徑所指定的程式即是解釋此指令碼檔案的Shell程式。如果首行沒有這句話,在執行指令碼檔案的時候,將會出現錯誤。後續的部分就是主程式,Shell指令碼像高階語言一樣,也有變數賦值,也有控制語句。除第一行外,以#開頭的行就是註釋行,直到此行的結束。如果一行未完成,可以在行尾加上",這個符號表明下一行與此行會合併為同一行。
編輯完畢,將指令碼存檔為filename.sh,檔名字尾sh表明這是一個Bash指令碼檔案。執行指令碼的時候,要先將指令碼檔案的屬性改為可執行的:
chmod +x filename.sh
執行指令碼的方法是:
./filename.sh
下面我們從經典的“hello world”入手,看一看最簡單的Shell指令碼的模樣。
#!/bin/sh
#print hello world in the console window
a = "hello world"
echo $a
ShellScript是一種弱型別語言,使用變數的時候無需首先宣告其型別。新的變數會在本地資料區分配記憶體進行儲存,這個變數歸當前的Shell所有,任何子程式都不能訪問本地變數。這些變數與環境變數不同,環境變數被儲存在另一記憶體區,叫做使用者環境區,這塊記憶體中的變數可以被子程式訪問。變數賦值的方式是:
variable_name = variable_value
如果對一個已經有值的變數賦值,新值將取代舊值。取值的時候要在變數名前加$,$variable_name可以在引號中使用,這一點和其他高階語言是明顯不同的。如果出現混淆的情況,可以使用花括號來區分,例如:
echo "Hi, $as"
就不會輸出“Hi, hello worlds”,而是輸出“Hi,”。這是因為Shell把$as當成一個變數,而$as未被賦值,其值為空。正確的方法是:
echo "Hi, ${a}s"
單引號中的變數不會進行變數替換操作。
關於變數,還需要知道幾個與其相關的Linux命令。
env用於顯示使用者環境區中的變數及其取值;set用於顯示本地資料區和使用者環境區中的變數及其取值;unset用於刪除指定變數當前的取值,該值將被指定為NULL;export命令用於將本地資料區中的變數轉移到使用者環境區。
下面我們來看一個更復雜的例子,結合這個例子,我們來講述Shell Script的語法。
2 # we have less than 3 arguments. Print the help text:
3 if [ $# -lt 3 ]; then
4 cat<<HELP
5 ren -- renames a number of files using sed regular expressions
6
7 USAGE: ren 'regexp' 'replacement' files
8 EXAMPLE: rename all *.HTM files in *.html:
9 ren 'HTM$' 'html' *.HTM
10
11 HELP
12 exit 0
13 fi
14 OLD="$1"
15 NEW="$2"
16 # The shift command removes one argument from the list of
17 # command line arguments.
18 shift
19 shift
20 # $* contains now all the files:
21 for file in $*; do
22 if [ -f "$file" ]; then
23 newfile=`echo "$file" | sed "s/${OLD}/${NEW}/g"`
24 if [ -f "$newfile" ]; then
25 echo "ERROR: $newfile exists already"
26 else
27 echo "renaming $file to $newfile "
28 mv "$file" "$newfile"
29 fi
30 fi
31 done
我們從頭來看,前面兩行上一個例子中已經解釋過了,從第三行開始,有新的內容。if語句和其他程式語言相似,都是流程控制語句。它的語法是:
if …; then
…
elif …; then
…
else
…
fi
與其他語言不同,Shell Script中if語句的條件部分要以分號來分隔。第三行中的[]表示條件測試,常用的條件測試有下面幾種:
[ -f "$file" ] 判斷$file是否是一個檔案
[ $a -lt 3 ] 判斷$a的值是否小於3,同樣-gt和-le分別表示大於或小於等於
[ -x "$file" ] 判斷$file是否存在且有可執行許可權,同樣-r測試檔案可讀性
[ -n "$a" ] 判斷變數$a是否有值,測試空串用-z
[ "$a" = "$b" ] 判斷$a和$b的取值是否相等
[ cond1 -a cond2 ] 判斷cond1和cond2是否同時成立,-o表示cond1和cond2有一成立
要注意條件測試部分中的空格。在方括號的兩側都有空格,在-f、-lt、=等符號兩側同樣也有空格。如果沒有這些空格,Shell解釋指令碼的時候就會出錯。
$#表示包括$0在內的命令列引數的個數。在Shell中,指令碼名稱本身是$0,剩下的依次是$0、$1、$2…、${10}、${11},等等。$*表示整個引數列表,不包括$0,也就是說不包括檔名的引數列表。
現在我們明白第三行的含義是如果指令碼檔案的引數少於三個,則執行if和fi語句之間的內容。然後,從第四行到第十一行之間的內容在ShellScript程式設計中被稱為Here文件,Here文件用於將多行文字傳遞給某一命令。Here文件的格式是以<<開始,後跟一個字串,在Here文件結束的時候,這個字串同樣也要出現,表示文件結束。在本例中,Here文件被輸出給cat命令,也即將文件內容列印在螢幕上,起到顯示幫助資訊的作用。
第十二行的exit是Linux的命令,表示退出當前程式。在Shell指令碼中可以使用所有的Linux命令,利用上面的cat和exit,從一方面來說,熟練使用Linux命令也可以大大減少Shell指令碼的長度。
十四、十五兩句是賦值語句,分別將第一和第二引數賦值給變數OLD和NEW。緊接下來的兩句是註釋,註釋下面的兩條shift的作用是將引數列表中的第一個和第二個引數刪除,後面的引數依次變為新的第一和第二引數,注意引數列表原本也不包括$0。
然後,自二十一行到三十一行是一個迴圈語句。Shell Script中的迴圈有下面幾種格式:
while [ cond1 ] && { || } [ cond2 ] …; do
…
done
for var in …; do
…
done
for (( cond1; cond2; cond3 )) do
…
done
until [ cond1 ] && { || } [ cond2 ] …; do
…
done
在上面這些迴圈中,也可以使用類似C語言中的break和continue語句中斷當前的迴圈操作。第二十一行的迴圈是將引數列表中的引數一個一個地放入變數file中。然後進入迴圈,判斷file是否為一個檔案,如果是檔案的話,則用sed命令搜尋和生成新的檔名。sed基本上可以看成一個查詢替換程式,從標準輸入,例如管道讀入文字,並將結果輸出到標準輸出,sed使用正規表示式進行搜尋。在第二十三行中,backtick(`)的作用是取出兩個backtick之間的命令輸出結果,在這裡,也就是將結果取出賦給變數newfile。此後,判斷newfile是否已經存在,否則就把file改成newfile。這樣我們就明白這個指令碼的作用了,ShellScript編寫的其他指令碼與此相似,只不過是語法和用法稍有不同而已。
通過這個例子我們明白了Shell Script的編寫規則,但還有幾件事情需要講述一下。
第一個,除了if語句之外,Shell Script中也有類似C語言中多分支結構的case語句,它的語法是:
case var in
pattern 1 )
… ;;
pattern 2 )
… ;;
*)
… ;;
esac
我們再就下面一個例子,看看case語句的用法。
while getopts vc: OPTION
do
case $OPTION in
c) COPIES=$OPTARG
ehco "$COPIES";;
v) echo "suyang";;
\?) exit 1;;
esac
done
上面的getopts類似於C語言提供的函式getopts,在Shell Script中,getopts經常和while語句聯合起來使用。getopts的語法如下:
getopts option_string variable
option_string中包含一串單字元選項,若getopts在命令列引數中發現了連字元,那麼它會將連字元之後的字元與option_string進行比較,若匹配成功,則把變數variable的值設為該選項,若無匹配,則把變數的值設為?。有時候,選項還會帶一個值,例如-c5等,這時要在option_string中該選項字母后面加上一個冒號,getopts發現冒號後,會讀取該值,然後將該值放入特殊變數OPTARG中。這個命令比較複雜,如有需要,讀者可以詳細參閱Shell編寫的相關資料。
上面這個迴圈的作用就是依次取出指令碼名稱後面的選項,進行處理,如果輸入了非法選項,則進入"?指定的部分,退出指令碼程式。
第二個,Bash提供了一種用於互動式應用的擴充套件select,使用者可以從一組不同的值中進行選擇。其語法如下:
select var in …; do
break;
done
例如,下面這段程式的輸出是:
#!/bin/bash
echo "Your choice?"
select var in "a" "b" "c"; do
break
done
echo $var
----------------------------
Your choice?
1) a
2) b
3) c
第三,Shell Script中也可以使用自定義的函式,其語法形式如下:
functionname()
{
…
}
例如我們可以把上面第二個例子中第四到第十二行放入一個名為help函式體內,以後每次呼叫的時候直接寫help即可。函式中處理函式呼叫引數的方法是,直接用上面講過的$1、$2來分別表示第一、第二個引數,用$*表示引數列表。
第四,我們也可以在Shell下除錯Shell Script指令碼,當然最簡單的方法就是用echo輸出檢視變數取值了。Bash也提供了真正的除錯方法,就是執行指令碼的時候用-x引數。
sh ?x filename.sh
這會執行指令碼並顯示指令碼中所有變數的取值,也可以使用引數-n,它並不執行指令碼,只是返回所有的語法錯誤。
相關文章
- Shell 程式設計入門程式設計
- csh shell程式設計入門程式設計
- shell程式設計入門指南程式設計
- Shell程式設計入門例項程式設計
- Linux入門---(三)Shell程式設計Linux程式設計
- 10分鐘入門Shell指令碼程式設計指令碼程式設計
- Shell指令碼程式設計30分鐘入門指令碼程式設計
- Linux下的shell程式設計入門(轉)Linux程式設計
- Linux-shell程式設計入門基礎Linux程式設計
- Shell程式設計基礎學習之六:sed 入門程式設計
- Shell程式設計入門:Linux直譯器原理(轉)程式設計Linux
- Shell程式設計-01-Shell指令碼初步入門程式設計指令碼
- 入門程式碼程式設計程式設計
- Linux命令列與shell指令碼程式設計入門經驗Linux命令列指令碼程式設計
- shell程式設計(三)輸入輸出程式設計
- 程式設計和網路程式設計入門程式設計
- shell程式設計程式設計
- 遊戲程式設計入門指南遊戲程式設計
- Number 1 — 程式設計入門程式設計
- Python程式設計入門Python程式設計
- TCSHshell程式設計入門(轉)程式設計
- 程式設計入門——壘積木學程式設計程式設計
- Linux Shell程式設計(1)——shell程式設計簡介Linux程式設計
- Shell程式設計 --- Shell介紹程式設計
- shell入門
- JAVA NIO程式設計入門(二)Java程式設計
- Flink DataStream 程式設計入門AST程式設計
- 程式設計入門學什麼?程式設計
- JAVA NIO程式設計入門(一)Java程式設計
- JAVA NIO 程式設計入門(三)Java程式設計
- java Swing程式設計入門Java程式設計
- 入門級的程式設計師程式設計師
- JavaScript 非同步程式設計入門JavaScript非同步程式設計
- Windows Shell 程式設計Windows程式設計
- shell程式設計(轉)程式設計
- shell程式設計二程式設計
- shell程式設計五程式設計
- shell簡介入門bash程式設計之執行(轉)程式設計