本文的主要內容:1、編寫Shell腳本的一般步驟
2、在Shell腳本中輸出文本 3、Shell腳本中的變量
4、Shell腳本中的函數 5、流程控制:if 分支結構
6、Shell中讀取鍵盤輸入一、編寫Shell 腳本
一般步驟:1.編寫一個腳本 2.使腳本文件可執行 3.把腳本放置到 shell 能夠找到的地方例如:
1.編寫hello_world腳本
#!/bin/bash # This is our first script. echo 'Hello World!'2.賦予可執行權限
chmod 700 hello_world3.執行腳本
./hello_world4.若想讓系統中的每個用戶都可以使用, 那麼可將腳本放到 /usr/local/bin,系統管理員使用的腳本經常放到 /usr/local/sbin 目錄下。
二、Shell中輸出文本使用echo方式
例如:
echo "a string"使用"here document"方式(可以隨意的嵌入引號)
格式如下:
command << token
text
token
這裡的 command 是一個可以接受標准輸入的命令名,token 是一個用來指示嵌入文本結束的字符串
把操作符"<<"改為 "<<-",shell 會忽略開頭的 tab 字符,可使用縮進提高可讀性
例如:
cat << _EOF_ a string _EOF_或
cat <<- _EOF_ a string _EOF_例子:使用 一個 here document 將一系列的命令傳遞到 ftp 程序中以從一個遠端 FTP 服務器中得到一個文件
#!/bin/bash # Script to retrieve a file via FTP FTP_SERVER=*** FTP_PATH=*** REMOTE_FILE=*** ftp -n << _EOF_ open $FTP_SERVER user anonymous me@linuxbox cd $FTP_PATH hash get $REMOTE_FILE bye _EOF_ ls -l $REMOTE_FILE三、Shell腳本中的變量
創建變量或給變量賦值variable=value(注:等號左右不能有空格)
可以在同一行中對多個變量賦值a=5 b="a string"
使用變量$variable 或 ${variable}
例如
b="a string" c="a string and $b" mv $filename ${filename}1
四、Shell中的函數函數語法形式(其中name為函數名,commands為一系列包含在函數中的命令,函數中須至少包含一條命令,return為可選)
function name {
commands
return
}
或
name () {
commands
return
}
*例如
#!/bin/bash function_1 () { echo "Function_1 executed." return } cat << _EOF_ $(function_1) _EOF_局部變量
*例如
funct_1 () { local foo #funct_1中的局部變量 foo=1 echo "funct_1: foo = $foo" }五、流程控制:if 分支結構
if 語句語法如下if commands; then
commands
[elif commands; then
commands...]
[else
commands]
fi
*例如:
x=5 if [ $x = 5 ]; then echo "x equals 5." else echo "x does not equal 5." fi退出狀態
當命令執行完畢後會給系統發送一個值,叫做退出狀態。Shell 提供了一個參數$?可用來檢查退出狀態
例如:(狀態0為命令執行成功)
$ ls -d /usr/bin
/usr/bin
$ echo $?
0
測試*經常與 if 一塊使用的命令是 test。test 命令執行各種各樣的檢查與比較,它有兩種等價模式:
test expression
或
[ expression ]
*其中expression 為一個表達式,其執行結果是 true 或者是 false。當表達式為真時,這個 test 命令返回一個0退出狀態,當表達式為假時,test 命令退出狀態為1
測試表達式*文件表達式
file1 -ef file2:file1 和 file2 擁有相同的索引號(通過硬鏈接兩個文件名指向相同的文件)
file1 -nt file2:file1新於 file2
file1 -ot file2:file1早於 file2
-b file:file 存在並且是一個塊(設備)文件
-c file:file 存在並且是一個字符(設備)文件
-d file:file 存在並且是一個目錄
-e file:file 存在
-f file:file 存在並且是一個普通文件
-g file:file 存在並且設置了組 ID
-G file:file 存在並且由有效組 ID 擁有
-k file:file 存在並且設置了它的“sticky bit”
-L file:file 存在並且是一個符號鏈接
-O file:file 存在並且由有效用戶 ID 擁有
-p file:file 存在並且是一個命名管道
-r file:file 存在並且可讀(有效用戶有可讀權限)
-s file:file 存在且其長度大於零
-S file:file 存在且是一個網絡 socket
-t fd:fd 是一個定向到終端/從終端定向的文件描述符 。 這可以被用來決定是否重定向了標准輸入/輸出錯誤
-u file:file 存在並且設置了 setuid 位
-w file:file 存在並且可寫(有效用戶擁有可寫權限)
-x file:file 存在並且可執行(有效用戶有執行/搜索權限)
*文件表達式例子(其中在表達式中參數$FILE兩邊的引號並不是必需的,但這可防范空參數)
test_file () { # test-file: Evaluate the status of a file FILE=~/.bashrc if [ -e "$FILE" ]; then if [ -f "$FILE" ]; then echo "$FILE is a regular file." fi if [ -d "$FILE" ]; then echo "$FILE is a directory." fi if [ -r "$FILE" ]; then echo "$FILE is readable." fi if [ -w "$FILE" ]; then echo "$FILE is writable." fi if [ -x "$FILE" ]; then echo "$FILE is executable/searchable." fi else echo "$FILE does not exist" return 1 fi }*字符串表達式
string:string 不為 null
-n string:字符串 string 的長度大於零
-z string:字符串 string 的長度為零
string1 = string2或string1 == string2:string1 和 string2 相同. 單或雙等號都可以,不過雙等號更受歡迎
string1 != string2:string1 和 string2 不相同
string1 > string2:sting1 排列在 string2 之後
string1 < string2:string1 排列在 string2 之前
注:> 和 <表達式操作符必須用引號引起來或者是用反斜槓轉義,否則會被 shell 解釋為重定向操作符,造成潛在地破壞結果
*字符串表達式例子:
#!/bin/bash # test-string: evaluate the value of a string ANSWER=maybe if [ -z "$ANSWER" ]; then echo "There is no answer." >&2 exit 1 fi if [ "$ANSWER" = "yes" ]; then echo "The answer is YES." elif [ "$ANSWER" = "no" ]; then echo "The answer is NO." elif [ "$ANSWER" = "maybe" ]; then echo "The answer is MAYBE." else echo "The answer is UNKNOWN." fi*整型表達式
integer1 -eq integer2:integer1 等於 integer2
integer1 -ne integer2:integer1 不等於 integer2
integer1 -le integer2:integer1 小於或等於 integer2
integer1 -lt integer2:integer1 小於 integer2
integer1 -ge integer2:integer1 大於或等於 integer2
integer1 -gt integer2:integer1 大於 integer2
*整型表達式例子:
#!/bin/bash # test-integer: evaluate the value of an integer. INT=-5 if [ -z "$INT" ]; then echo "INT is empty." >&2 exit 1 fi if [ $INT -eq 0 ]; then echo "INT is zero." else if [ $INT -lt 0 ]; then echo "INT is negative." else echo "INT is positive." fi if [ $((INT % 2)) -eq 0 ]; then echo "INT is even." else echo "INT is odd." fi fi更現代的測試版本
*目前的 bash 版本包含一個復合命令:[[ expression ]],與test相比增加了一個重要的新的字符串表達式:string1 =~ regex,若string1匹配擴展的正則表達式 regex則返回真
例子:
#!/bin/bash # test-integer2: evaluate the value of an integer. INT=-5 if [[ "$INT" =~ ^-?[0-9]+$ ]]; then if [ $INT -eq 0 ]; then echo "INT is zero." else if [ $INT -lt 0 ]; then echo "INT is negative." else echo "INT is positive." fi if [ $((INT % 2)) -eq 0 ]; then echo "INT is even." else echo "INT is odd." fi fi else echo "INT is not an integer." >&2 exit 1 fi*為整數設計的復合命令:(( ))
例子:
#!/bin/bash # test-integer2a: evaluate the value of an integer. INT=-5 if [[ "$INT" =~ ^-?[0-9]+$ ]]; then if ((INT == 0)); then echo "INT is zero." else if ((INT < 0)); then echo "INT is negative." else echo "INT is positive." fi if (( ((INT % 2)) == 0)); then echo "INT is even." else echo "INT is odd." fi fi else echo "INT is not an integer." >&2 exit 1 fi通過使用邏輯操作符來結合表達式
操作符測 試[[ ]] 和 (( ))AND-a&&OR-o||NOT!!控制操作符:分支的另一種方法*bash 支持兩種可以執行分支任務的控制操作符。這個 &&(AND)和||(OR)操作符作用如同復合命令[[ ]]中的邏輯操作符
*語法:command1 && command2 和 command1 || command2
*對於 && 操作符,只有當command1 執行成功後,才會執行 command2。對於 || 操作符,只有當command1 執行失敗後, 才會執行command2
*例如:
$ mkdir temp && cd temp :在成功創建目錄temp後跳轉到temp
$ [ -d temp ] || mkdir temp :若目錄 temp 不存在則創建這個目錄
[ -d temp ] || exit 1 : 若目錄temp不存在則返回退出狀態1
六、讀取鍵盤輸入(交互)read - 從標准輸入讀取單行數據
*語法形式:read [-options] [variable...]
*讀取一個整數:
echo -n "Please enter an integer -> " read var echo "var = '$var'"*給多個變量賦值:
echo -n "Enter one or more values > " read var1 var2 echo "var1 = '$var1'" echo "var2 = '$var2'"*若沒有提供變量名,shell 變量 REPLY 會包含數據行
echo -n "Enter one or more values > " read echo "REPLY = '$REPLY'"*read選項
-a array:把輸入賦值到數組 array 中,從索引號零開始
-d delimiter:用字符串 delimiter 中的第一個字符指示輸入結束,而不是一個換行符
-e:使用 Readline 來處理輸入。這使得與命令行相同的方式編輯輸入
-n num:讀取 num 個輸入字符,而不是整行
-p prompt:為輸入顯示提示信息,使用字符串 prompt
-r:Raw mode. 不把反斜槓字符解釋為轉義字符
-s:Silent mode. 不會在屏幕上顯示輸入的字符。當輸入密碼和其它確認信息的時候,這會很有幫助
-t seconds:超時. 幾秒鐘後終止輸入。read 會返回一個非零退出狀態,若輸入超時
-u fd:使用文件描述符 fd 中的輸入,而不是標准輸入
*read選項例子:
#!/bin/bash if read -t 10 -sp "Enter secret pass phrase > " secret_pass; then echo -e "\nSecret pass phrase = '$secret_pass'" else echo -e "\nInput timed out" >&2 exit 1 fi*此腳本提示用戶輸入一個密碼,若在10秒內沒有完成輸入,則腳本會退出並返回一個錯誤。因包含了一個 -s 選項,所以輸入的密碼不會出現在屏幕上。校正輸入
*校正各種輸入的示例程序:
#!/bin/bash invalid_input () { echo "Invalid input '$REPLY'" >&2 exit 1 } read -p "Enter a single item > " # input is empty (invalid) [[ -z $REPLY ]] && invalid_input # input is multiple items (invalid) (( $(echo $REPLY | wc -w) > 1 )) && invalid_input # is input a valid filename? if [[ $REPLY =~ ^[-[:alnum:]\._]+$ ]]; then echo "'$REPLY' is a valid filename." if [[ -e $REPLY ]]; then echo "And file '$REPLY' exists." else echo "However, file '$REPLY' does not exist." fi # is input a floating point number? if [[ $REPLY =~ ^-?[[:digit:]]*\.[[:digit:]]+$ ]]; then echo "'$REPLY' is a floating point number." else echo "'$REPLY' is not a floating point number." fi # is input an integer? if [[ $REPLY =~ ^-?[[:digit:]]+$ ]]; then echo "'$REPLY' is an integer." else echo "'$REPLY' is not an integer." fi else echo "The string '$REPLY' is not a valid filename." fi菜單,一種常見的交互類型稱為菜單驅動
*菜單驅動例子
#!/bin/bash # read-menu: a menu driven system information program clear echo " Please Select: 1. Display System Information 2. Display Disk Space 3. Display Home Space Utilization 0. Quit " read -p "Enter selection [0-3] > " if [[ $REPLY =~ ^[0-3]$ ]]; then if [[ $REPLY == 0 ]]; then echo "Program terminated." exit fi if [[ $REPLY == 1 ]]; then echo "Hostname: $HOSTNAME" uptime exit fi if [[ $REPLY == 2 ]]; then df -h exit fi if [[ $REPLY == 3 ]]; then if [[ $(id -u) -eq 0 ]]; then echo "Home Space Utilization (All Users)" du -sh /home/* else echo "Home Space Utilization ($USER)" du -sh $HOME fi exit fi else echo "Invalid entry." >&2 exit 1 fi*從邏輯上講,這個腳本被分為兩部分。第一部分顯示菜單和用戶輸入。第二部分確認用戶反饋,並執行 選擇的行動參考:《The Linux Command Line》