Bash Shell要完整深入的掌握,需要花一定的時間,但是有時候工作需要,需要快速的掌握其基本用法並編寫簡單的程式來滿足項目的需要,那麼您就可以看看下面的文章,否則沒必要花時間在下面的文字上。
首先要澄清的是,這裡不是要對shell 指令碼編程作詳細的研究,正如本文標題所指出的,這是一篇介紹bashshell 指令碼編寫文法的快速指南。如果你想深入研究,那麼建議你買一本關於shell指令碼編程的書 ;-) 。好,現在開始我們的學習,開始用停表計時吧!
本文:
常見的環境變數:
$PATH - 為可執行程式設定尋找路徑,與msdos下的$PATH 變數類似。
$HOME - 使用者的本地目錄(home).
$MAIL - 儲存使用者佈建的mail投遞路徑。
儲存了一串 在命令列中用於 字元分隔 的字元 組成的字串。這個字串通常包含了空格,定位字元,分行符號。要查看之,你要做一個octal dump 的操作 如下:
$ echo $IFS | od -bc
PS1 and PS2 - 第一順序提示符和第二順序提示符(Primary and secondary prompts). PS1 預設設為 $ , PS2 設定為 '>' . 查看PS2可以通過如下命令:
$ ls |
然後按斷行符號。
$USER - 使用者登陸名。
$TERM - 終端類型標識。有時必須為編輯器設定正確的終端標識,以便其正常工作。
$SHELL - 登陸時可通過此查看shell 的類型.
注意:要查看以上變數的值,只要簡單地用 echo 命令 加 $變數名就行了。例如:
$ echo $USER
ravi
就得到了$USER 的值。
bash shell 編程規則
1) 編寫的指令碼首行必須為:
#!/bin/bash
#井號,後跟!歎號,接著是shell的路徑。這個語句能夠告訴解析器這是一個shell指令碼,同時指定shell的路徑。
2)執行指令碼前,先為指令碼賦執行許可權:
$ chmod ugo+x your_shell_script.sh
3)把指令碼以.sh尾碼命名。這讓人知道這是一個shell指令碼。這不是必須的,但是這是規範,沒錯,規範。
條件陳述式
if
if 語句-對條件命令進行判斷然後決定流程的執行。
藍色的字必要的。紅色的則是可選的。
文法:
if condition_is_true
then
execute commands
else
execute commands
fi
if 條件可以是多路選擇(分支結構)。這樣可以對多條件進行判斷。
if condition_is_true
then
execute commands
elif another_condition_is_true
then
execute commands
else
execute commands
fi
例子:
if grep "linuxhelp" thisfile.html
then
echo "Found the word in the file"
else
echo "Sorry no luck!"
fi
if 的搭檔- test命令
test 是shell的一個內建命令。test對右邊的運算元進行判斷。返回true或false.為此,test 用特定的操作符來作條件判斷,如下所示:
關係型操作符
-eq Equal to等於
-lt Less than小於
-gt Greater than大於
-ge Greater than or equal to大於等於
-lt Less than小於
-le Less than or equal to 小於等於
檔案相關的測試:
-f file 存在且為常規檔案,則為真
-r file 檔案存在且可讀,則為真
-w file 檔案存在且可寫,則為真
-x file 檔案存在且可執行,則為真
-d file 為檔案夾,則為真
-s file 檔案存在且不為零則為真
字串測試:
-n str True if string str is not a null string
-z str True if string str is a null string
str1 == str2 True if both strings are equal
str1 != str2 True if both strings are unequal
str True if string str is assigned a value
and is not null.
上面的意思是:
-n str 如果str非空則為真
-z str 如果str為空白則為真
str1 == str2 如果兩個字串相等則為真
str1 != str2 如果兩個字串不等則為真
str 如果str有賦非空值則為真。
test 函數 也允許在一行中同時檢驗多個運算式。
-a Performs the
AND function
-o Performs the
OR function
舉例:
test $d -eq 25 ; echo $d
上面的意思是:如果$d變數的值等於25,則輸出這個值。
test $s -lt 50; do_something
if [ $d -eq 25 ]
then
echo $d
fi
在上面的例子中,我用中括弧標記的,由test 處理,其實,用如下的方式也可以處理:
if
[ $str1 == $str2
]
then
do something
fi
if [
-n "$str1" -a -n "$str2" ]
then
echo 'Both $str1 and $str2 are not null'
fi
上面的意思是:如果兩個字串都不為null ,就執行 echo 命令。
用test時的注意事項:
如果你用[ ] 替代test,那麼請在]前和[後加上空格,否則將不能解析。
注意:test的運算元限制為整數,小數將會被自動截斷。
不要用萬用字元來檢查字串的匹配性。在shell 中,萬用字元用來匹配目錄中有共同名稱的的檔案名稱,而不用於test命令。
case 語句
case 是shell 提供的另一個作為條件判斷的語句。
文法:
case expression in
pattern1) execute commands ;;
pattern2) execute commands ;;
...
esac
The keywords here are in, case and esac. The ';;' is used as option terminators. The construct also uses ')' to delimit the pattern from the action.
文法中有case,in和esac三個關鍵字。
符號;; 是各個選項的結尾標記。
而右括弧)用於分割pattern和動作。
Example:
...
echo "Enter your option : "
read i;
case $i in
1) ls -l ;;
2) ps -aux ;;
3) date ;;
4) who ;;
5) exit
esac
註:最後一個選項是不需要;;作結的,當然你喜歡,也可以加上。
另一個例子:
case `date |cut -d" " -f1` in
Mon) commands ;;
Tue) commands ;;
Wed) commands ;;
...
esac
case 可以匹配一個以上的模式(pattern),你可以用萬用字元來匹配模式;
...
echo "Do you wish to continue? (y/n)"
read ans
case $ans in
Y|y) ;;
[Yy][Ee][Ss]) ;;
N|n) exit ;;
[Nn][Oo]) exit ;;
*) echo "Invalid command"
esac
在以上的例子中,如果你輸入 YeS, YES,yEs 或者任何其他的組合,都可以被匹配到。
到此,條件陳述式的介紹告一段落。
迴圈語句
while 迴圈
文法:
while condition_is_true
do
execute commands
done
舉例:
while [ $num -gt 100 ]
do
sleep 5
done
while :
do
execute some commands
done
以上代碼將會執行一個無限的迴圈,當然你可以使用while true來代替while : 。
在此我將會介紹和迴圈相關的關鍵字:break和continue.
break - 這個關鍵字能夠退出迴圈,終止執行。
continue - 這個關鍵字可以暫停當前迴圈中跟在其後的語句的執行,轉而執行下一個迴圈。
until 迴圈
如果until 後的條件為false,那麼就一直迴圈地執行do 中的命令。
until false
do
execute commands
done
...
until [ -r myfile ]
do
sleep 5
done
The above code is executed repeatedly until the file myfile can be read.
以上代碼將會重複執行,直到myfile是可讀的。
for 迴圈
文法:
for variablein list
do
execute commands
done
舉例:
...
for x
in 1 2 3 4 5
do
echo "The value of x is $x";
done
上面例子中,列舉了1-5五個數。
下面是另一個例子:
for var
in $PATH $MAIL $HOME
do
echo $var
done
如果你有一個檔案夾,裡面都是要編譯的*.java檔案
那麼你可以寫一個這樣的shell指令碼:
...
for file
in *.java
do
javac $file
done
注意:如上面的例子所示,指令碼裡是可以用萬用字元的。
寫shell指令碼是的一些特殊符號和含義:
$* - This denotes all the parameters passed to the script
at the time of its execution. Which includes $1, $2
and so on.
$0 - Name of the shell script being executed.
$# - Number of arguments specified in the command line.
$? - Exit status of the last command.
以上的符號我們稱之為位置參數。讓我通過如下的例子來解析位置參數的用法。
假設我有一個指令碼my_script.sh,並執行如下:
$ ./my_script.sh linux is a robust OS
如上所示,我給指令碼傳遞了5個參數。在此,位置參數的取值為:
$* - 的取值包含了'linux','is','a','robust','OS'.
$0 - 的取值是my_script.sh -所執行的指令檔的名稱。
$# - 取值為5-參數的個數。
$$ - 取值為當前進程的id.你可以在執行指令碼時為所建立的臨時檔案(如果有)
用這個參數來命名以得到一個唯一的名稱。
$1 - 第一個參數的值 ,即 'linux'
$2 - 第一個參數的值 ,即 'is'
...等等。
set 和 shift 語句
set - 為位置參數關聯一個取值。
例如:
$ set `date`
$ echo $1
$ echo $*
$ echo $#
$ echo $2
shift - 把位置參數的值直接轉移給下一個參數(編號小一級的位置參數)。
每執行一次shift,就轉移一次。
舉例:
$ set `date`
$ echo $1 $2 $3
$ shift
$ echo $1 $2 $3
$ shift
$ echo $1 $2 $3
查看當前shell指令碼執行的進程id,可以用:
$ echo $$
2667
並可以用如下指令碼驗證:
$ ps -f |grep bash
read 語句
read 可以使得你的shell 指令碼實現人機互動。
使用read 語句可以讓使用者在執行shell的時候設定變數的值。
當指令碼執行到read語句時,將會暫停而等待使用者用鍵盤輸入變數值,
讀入值後,shell程式繼續執行。
例如:
#!/bin/sh
echo "Enter your name : "
read name
echo "Hello $name , Have a nice day."
退出狀態/傳回值
Exit status of the last command
每一個命令執行完之後都會有一個值被返回。這個值叫做退出狀態或者傳回值。如果命令被成功執行,將會返回true,否則返回false.這可以通過使用位置參數$?來檢查。
本文中,對bash shell 的指令碼編寫做了簡明的介紹,但是其實還有更多的shell編程知識沒有談及。對我們而言,shell 有幾種,bash shell 只是其中之一。每種shell在文法上都有少許的差異。比如c shell,其文法有和c語言很相似。而在這裡介紹的內容對於各種shell都適用。