腳本不是復雜的程序,它是按行解釋的,腳本的第一行總是以#!/bin/sh開始.
這行代碼通知書shell使用系統上的Bourne shell解析器.
shell語法
test 命令
1.條件測試
test命令用于測試字符串,文件狀態和數字.
工作原理
test 命令最短的定義可能是評估一個表達式;如果條件為真,則返回一個 0 值。如果表達式不為真,返回非0
test一般有兩種格式:
test 條件表達式
或
[ 條件表達式 ]
使用方括號時,要注意在條件兩邊加上空格.
文件運算符
利用這些運算符,您可以在程序中根據對文件類型的評估結果執行不同的操作:
-b file 如果文件為一個塊特殊文件,則為真
-c file 如果文件為一個字符特殊文件,則為真
-d file 如果文件為一個目錄,則為真
-e file 如果文件存在,則為真
-f file 如果文件為一個普通文件,則為真
-g file 如果設置了文件的 SGID 位,則為真
-G file 如果文件存在且歸該組所有,則為真
-k file 如果設置了文件的粘著位,則為真
-O file 如果文件存在并且歸該用戶所有,則為真
-p file 如果文件為一個命名管道,則為真
-r file 如果文件可讀,則為真
-s file 如果文件的長度不為零,則為真
-S file 如果文件為一個套接字特殊文件,則為真
-t fd 如果 fd 是一個與終端相連的打開的文件描述符(fd 默認為 1),則為真
-u file 如果設置了文件的 SUID 位,則為真
-w file 如果文件可寫,則為真
-x file 如果文件可執行,則為真
字符串比較運算符
如標題所示,這組函數比較字符串的值。您可以檢查它們是否存在、是否相同或者是否不同。
string 測試以判斷字符串是否不為空
-n string 測試以判斷字符串是否不為空;
-z string 測試以判斷字符串是否為空;
string1 = string2 測試以判斷 string1 是否與 string2 相同
string1 != string2 測試以判斷 string1 是否與 string2 不同
整數比較運算符
正如字符串比較運算符驗證字符串相等或不同一樣,整數比較運算符對數字執行相同的功能。
如果變量的值匹配則表達式測試為真,如果不匹配,則為假。整數比較運算符不處理字符串(正如字符串運算符不處理數字一樣):
-eq 等于
-ge 大于或等于
-gt 大于
-le 小于或等于
-lt 小于
-ne 不等于
如:
# [ 2 -gt 3 ]
# echo $?
1
# [ 2 -lt 3 ]
# echo $?
0
布爾運算符
布爾運算符在幾乎每種語言中的工作方式都相同 — 包括 shell 腳本。在 nutshell 中,它們檢查多個條件為真或為假,或者針對假的條件而不是真的條件采取操作。與 test 搭配使用的運算符有:
! 條件非
-a 條件與
-o 條件或
控制結構
無論什么編程語言都離不開條件判斷。SHELL也不例外。
條件分支
if語句
語法1:
if 條件表達式
then 命令
fi
語法2:
if 條件表達式; then
do something here
elif 條件表達式 then
do another thing here
else
do something else here
fi
使用if時,必須將then部分放在新行,否則會報錯.
如果要不分行,必須使用命令分隔符.
$ vi testsh.sh
#!/bin/sh
if
cat 111-tmp.txt | grep ting1
then
echo found
else
echo "no found"
fi
$ vi testsh.sh
#!/bin/sh
cat 111-tmp.txt | grep ting1
if [ $? -eq 0 ]
then
echo $?
echo found
else
echo $?
echo "no found"
fi
#!/bin/sh
#函數
gw()
{
echo "do function gw()"
return 0
}
if gw
then
echo "run succeed"
echo "run succeed"
else
echo "run failed"
echo "run failed"
fi
說明:
if 命令/函數 0為真,走then
if 多條指令,這些命令之間相當于“and”(與)
case語句
case命令可類比C語言的switch/case語句,esac表示case語句塊的結束。
每個匹配分支可以有若干條命令,末尾必須以;;結束,執行時找到第一個匹配的分支并執行相應的命令,然后直接跳到esac之后,不需要像C語言一樣用break跳出。
如:
#! /bin/sh
echo "Is it morning? Please answer yes or no."
read YES_OR_NO
case "$YES_OR_NO" in
yes|y|Yes|YES)
echo "Good Morning!";;
[nN]*)
echo "Good Afternoon!";;
*)
echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."
exit 1;;
esac
exit 0
for語句
for 變量名 in 列表
do
命令1
命令2
done
Shell腳本的for循環結構和C語言很不一樣,它類似php編程語言的foreach循環。例如:
#!/bin/sh
for FRUIT in apple banana pear; do
echo "I like $FRUIT"
done
while/do/done
while的用法和C語言類似。比如一個驗證密碼的腳本:
#!/bin/sh
echo "Enter password:"
read TRY
while [ "$TRY" != "secret" ]; do
echo "Sorry, try again"
read TRY
done
位置參數和特殊變量
$0 相當于C語言main函數的argv[0]
$1、$2
這些稱為位置參數(Positional Parameter),相當于C語言main函數的argv[1]、argv[2]
$# 參數個數,不包括程序自身,相當于C語言main函數的argc-1
$@ 表示參數列表"$1" "$2"
,例如可以用在for循環中的in后面。
$? 上一條命令的Exit Status
$$ 當前Shell的進程號
位置參數可以用shift命令左移。
比如shift 3表示原來的$4現在變成$1,原來的$5現在變成$2等等,原來的$1、$2、$3丟棄,$0不移動。不帶參數的shift命令相當于shift 1。
函數
和C語言類似,Shell中也有函數的概念,但是函數定義中沒有返回值也沒有參數列表。例如:
#!/bin/sh
foo(){ echo "Function foo is called";}
echo "-=start=-"
foo
echo "-=end=-"
注意函數體的左花括號{和后面的命令之間必須有空格或換行,如果將最后一條命令和右花括號}寫在同一行,命令末尾必須有;號。
在定義foo()函數時并不執行函數體中的命令,就像定義變量一樣,只是給foo這個名字一個定義,到后面調用foo函數的時候(注意Shell中的函數調用不寫括號)才執行函數體中的命令。Shell腳本中的函數必須先定義后調用,一般把函數定義都寫在腳本的前面,把函數調用和其它命令寫在腳本的最后(類似C語言中的main函數,這才是整個腳本實際開始執行命令的地方)。
Shell函數沒有參數列表并不表示不能傳參數,事實上,函數就像是迷你腳本,調用函數時可以傳任意個參數,在函數內同樣是用$0、$1、$2等變量來提取參數,函數中的位置參數相當于函數的局部變量,改變這些變量并不會影響函數外面的$0、$1、$2等變量。函數中可以用return命令返回,如果return后面跟一個數字則表示函數的Exit Status。
until語句
until循環執行一系列命令直至條件為真時停止。注意,這里是直到條件是真時才停止
until格式為:
until 條件
命令1

done
i=0
until [ $i -gt 3 ]
do
i=`expr "$i" + 1`
#i=$(($i + 1))
echo $i
done