linux 下最重要的指令碼語言算是 bash 了,我也就寫點這個吧(我也只會這個:))。跟其他開發語言(如C)比,bash
是比較簡單的一種語言,主要用於寫一些指令碼代碼,一些批處理或安裝程式。你可以看看在/etc/init.d/目錄下,那裡就有很多用來控制各個服務的腳
本檔案。
先看一個“hello world!”的例子:
在某個目錄下建立一個檔案,叫hello.sh,敲入以下代碼:
#!/bin/sh
echo "hello world!"
好,就這些。儲存,在命令提示字元下進入儲存“hello.sh”的目錄,這樣執行:
#sh hello.sh(斷行符號)
看到了吧?哈哈,不過你高興的不要太早了,只並不能說明什麼,就象你在其他編程環境中做的“hello world.”一樣,離高手的距離還遠著呢。
我們先看看bash指令碼中變數的使用。
修改上面的“hello world!”的例子,改成下面的樣子:
#!/bin/bash
# This is a very simple example
str="hello world!"
echo $str
儲存後按照上面的方法執行該指令碼,你將看到和以前一樣的效果。我們看看每一句的意義:
第
一行,#! 是說明 hello.sh 這個檔案的類型的,有點類似 Windows 系統下用檔案尾碼來表示不同檔案類型的意思。Linux 系統根據
"#!" 及該字串後面的資訊確定該檔案的類型。在 BASH 中 第一行的 "#!" 及後面的 "/bin/bash" 就表明該檔案是一個
BASH 程式,需要由 /bin 目錄下的 bash 程式來解釋執行。BASH 這個程式一般是存放在 /bin 目錄下。這一行的寫法是固定的。
第二行的 "# This is a ..." 就是 BASH 程式的注釋,在 BASH 程式中從“#”號(沒有“!”號)開始到行尾的部分均被看作是程式的注釋,相當於C/C++語言中的“//”。
第三行是為一個名稱為 str 的變數賦值。
第四行的 echo 語句的功能是把 echo 後面的字串或變數的內容輸出到標準輸出中去。需要注意的是 BASH 中的絕大多數語句結尾處都沒有分號。
對
於第三行,可能有人會問:在C/C++中,變數都屬於某個類型,在這變數 str 的類型是什麼呢?在 BASH 中變數定義是不需要的,沒有 "int
i"
這樣的定義過程。如果想用一個變數,只要他沒有在前面被定義過,就直接可以用,當然你使用該變數的第一條語句應該是對他賦初值了,如果你不賦初值也沒關
系,只不過該變數是空( 注意:是 NULL,不是 0 )。
關於變數的使用,要注意以下幾點:
一,變數賦值時,“=”左右兩邊都不能有空格;
二,BASH 中的語句結尾不需要分號(";");
三,除了在變數賦值和在FOR迴圈語句頭中,BASH 中的變數使用必須在變數前加"$"符號。
在比較詳細的 bash 文檔中,會規定使用變數要採用這樣的形式:${STR},如果你的指令碼出了莫名其妙的錯誤,不妨看看是不是這個問題造成的。
BASH 中的變數既然不需要定義,也就沒有類型一說,那是不是一個變數既可以存放整數,也可以存放字串呢?對!
一個變數即可以被定義為一個字串,也可以被再定義為整數。如果對該變數進行整數運算,他就被解釋為整數;如果對他進行字串操作,他就被看作為一個字串。請看下面的例子:
#!/bin/bash
x=2006
let "x = $x + 1"
echo $x
x="a string."
echo $x
執行一下看看?
又
出現了新的關鍵字:let。關於整數變數計算,有如下幾種:" + - * / %
",他們的意思和字面意思相同,在*和/之前必須冠以反斜線,已防被SHELL先行解釋。整數運算一般通過 let 和 expr
這兩個指令來實現,如對變數 x 加 1 可以寫作:let "x = $x + 1" 或者 x=`expr $x + 1`
關於運行時參數,我們在執行指令碼時有時很想傳個參數進去,如:#sh mysh.sh hdz(斷行符號)好,很簡單,在 bash 中,使用這樣傳進來的變數時也要在前面加“$”符號。
$# 傳入指令碼的命令列參數個數;
$* 所有命令列參數值,在各個參數值之間留有空格;
位置變元
$0 命令本身(shell檔案名稱)
$1 第一個命令列參數;
$2 第二個命令列參數;
...
好,編輯以下指令碼:
#!/bin/sh
echo "number of vars:"$#
echo "values of vars:"$*
echo "value of var1:"$1
echo "value of var2:"$2
echo "value of var3:"$3
echo "value of var4:"$4
儲存檔案名稱為 my.sh,執行時傳入參數:#sh my.sh a b c d e(斷行符號),看到結果你就會更清楚各個變數的意思。如果訪問的參數在執行時沒有傳入,如有一條這樣的代碼:
echo "value of var4:"$100
而在執行時並沒有輸入100個參數,那取得的值為 NULL。
在 BASH 程式中如果一個變數被使用了,那麼直到該程式的結尾,該變數都一直有效。為了使得某個變數存在於一個局部程式塊中,就引入了局部變數的概念。BASH 中,在變數首次被賦初值時加上 local 關鍵字就可以聲明一個局部變數,如下面這個例子:
#!/bin/bash
HELLO="var1"
echo $HELLO
function hello {
local HELLO="var2"
echo $HELLO
}
echo $HELLO
該程式的執行結果是:
var1
var2
var1
這個執行結果表明全域變數 $HELLO 的值在執行函數 hello 時並沒有被改變。也就是說局部變數 $HELLO 的影響只存在於函數那個程式塊中。
BASH 中的變數與 C 語言中變數的區別
這裡我們為原來不熟悉 BASH 編程,但是非常熟悉 C 語言的程式員總結一下在 BASH 環境中使用變數需要注意的問題。
1,BASH 中的變數在引用時都需要在變數前加上 "$" 符號( 第一次賦值及在For迴圈的頭部不用加 "$"符號 );
2,BASH 中沒有浮點運算,因此也就沒有浮點類型的變數可用;
3,BASH 中的整形變數的比較符號與 C 語言中完全不同,而且整形變數的算術運算也需要經過 let 或 expr 語句來處理;
下面我們來看看變數之間的比較操作:
在比較操作上,整數變數和字串變數各不相同,詳見下表:
對應的操作 整數操作 字串操作
相同 -eq =
不同 -ne !=
大於 -gt >
小於 -lt <
大於或等於 -ge
小於或等於 -le
為空白 -z
不為空白 -n
比如:
比較整數 a 和 b 是否相等就寫做 if [ $a = $b ]
判斷整數 a 是否大於整數 b 就寫做 if [ $a -gt $b ]
比較字串 a 和 b 是否相等就寫作:if [ $a = $b ]
判斷字串 a 是否為空白就寫作: if [ -z $a ]
判斷整數變數 a 是否大於 b 就寫作:if [ $a -gt $b ]
注意:在“[”和“]”符號的左右都留有空格。
BASH 是 Linux 作業系統的 Shell,因此系統的檔案必然是 BASH 需要操作的重要對象
運算子,下面說說對檔案的操作:
含義( 滿足下面要求時返回 TRUE )
-e 檔案已經存在
-f 檔案是普通檔案
-s 檔案大小不為零
-d 檔案是一個目錄
-r 檔案對目前使用者可以讀取
-w 檔案對目前使用者可以寫入
-x 檔案對目前使用者可以執行
-g 檔案的 GID 標誌被設定
-u 檔案的 UID 標誌被設定
-O 檔案是屬於目前使用者的
-G 檔案的組 ID 和目前使用者相同
file1 -nt file2 檔案 file1 比 file2 更新
file1 -ot file2 檔案 file1 比 file2 更老
如 if [ -x /root ] 可以用於判斷 /root 目錄是否可以被目前使用者進入。
上面有進行比較的 if 關鍵字,是的,bash 中有和 C 語言相似的流程式控制制語句,主要有:if、for、while、until、case 等語句。下面較詳細的介紹一下。
if 語句用於判斷和分支,其文法規則和 C 語言的 if 非常相似。其幾種基本結構為:
if [ expression ]
then
#code block
fi
或者
if [ expression ]
then
#code block
else
#code block
fi
或者
if [ expression ]
then
#code block
else if [ expression ]
then
#code block
else
#code block
fi
或者
if [ expression ]
then
#code block
elif [ expression ]
then
#code block
else
#code block
fi
如
果您為了簡潔,想把 then 和 if 放在一行,那就要這樣寫了:if [ expression ]; then。即在 then
前加一個“;”號(bash 裡面每行的結束處沒有分號,那要把兩行的內容寫到一行,是不是要用“;”號隔開啊?哈哈,對!這樣說來,“if [
expression ]; then”只是把兩行內容寫到了一行,沒有什麼新的東西。)。
for 迴圈結構與 C 語言中有所不同,在 BASH 中 for 迴圈的基本結構是:
for $var in [list]
do
#code block
done
其
中 $var 是迴圈控制變數,[list] 是 var 需要遍曆的一個集合,do/done 對包含了迴圈體,相當於 C
語言中的一對大括弧。另外如果do 和 for 被寫在同一行,必須在 do 前面加上 ";"。如: for $var in [list]; do
。下面是一個運用 for 進行迴圈的例子:
#!/bin/bash
for day in Sun Mon Tue Wed Thu Fri Sat
do
echo $day
done
# 如果列表被包含在一對雙引號中,則被認為是一個元素
for day in "Sun Mon Tue Wed Thu Fri Sat"
do
echo $day
done
exit 0
注意上面的例子中,在 for 所在那行的變數 day 是沒有加 "$" 符號的,而在迴圈體內,echo 所在行變數 $day 是必須加上
"$" 符號的。另外如果寫成 for day 而沒有後面的 in [list] 部分,則 day 將取遍命令列的所有參數。如這個程式:
#!/bin/bash
for param
do
echo $param
done
exit 0
上面這個程式將列出所有命令列參數。for 迴圈結構的迴圈體被包含在 do/done 對中,這也是後面的 while、until 迴圈所具有的特點。
while 迴圈的基本結構是:
while [ condition ]
do
#code block
done
這個結構請大家自己編寫一個例子來驗證。
until 迴圈的基本結構是:
until [ condition is TRUE ]
do
#code block
done
這個結構也請大家自己編寫一個例子來驗證。
case
BASH 中的 case 結構與 C 語言中的 switch 語句的功能比較類似,可以用於進行多項分支控制。其基本結構是:
case "$var" in
condition1 )
;;
condition2 )
;;
* )
default statments;;
esac
下面這個程式是運用 case 結構進行分支執行的例子:
#!/bin/bash
echo "Hit a key, then hit return."
read Keypress
case "$Keypress" in
[a-z] ) echo "Lowercase letter";;
[A-Z] ) echo "Uppercase letter";;
[0-9] ) echo "Digit";;
* ) echo "Punctuation, whitespace, or other";;
esac
exit 0
上面例子中的第四行 "read Keypress" 一句中的 read 語句表示從鍵盤上讀取輸入。這個命令將在本講義的 BASH 的其他進階問題中講解。
break/continue
熟悉 C 語言編程的都很熟悉 break 語句和 continue 語句。BASH 中同樣有這兩條語句,而且作用和用法也和 C
語言中相同,break 語句可以讓程式流程從當前迴圈體中完全跳出,而 continue 語句可以跳過當次迴圈的剩餘部分並直接進入下一次迴圈。
關於bash在控制台下的快速鍵
ctrl+u 刪除游標以前的所有字元
ctrl+d 刪除游標以前的一個字元
ctrl+k 刪除游標以後的所有字元
ctrl+h 刪除游標以後的一個字元
ctrl+t 調換游標前兩個字元的次序
ctrl+a 移動游標到最前面
ctrl+e 移動游標到最後面
ctrl+p 上一個命令
ctrl+n 下一個命令
ctrl+s 鎖定輸入
ctrl+q 解除鎖定
ctrl+f 移動游標到後一個字元
ctrl+b 移動游標到前一個字元
ctrl+x 標記一個位置
ctrl+c 清除當前的輸入