1. 程式人生 > >linux開發之shell程式設計

linux開發之shell程式設計


1、第一個shell程式
  #!/bin/bash

  echo "What is your name?"
  read PERSON
  echo "Hello, $PERSON"

備註:(1)“#!” 是一個約定的標記,它告訴系統這個指令碼需要什麼直譯器來執行,即使用哪一種Shell。echo命令用於向視窗輸出文字;
      (2)echo 是一個輸出命令,可以用來輸出數字、變數、字串等;
      (3)read read 命令從 stdin 獲取輸入並賦值給 PERSON 變數,最後在 stdout 上輸出;
      (4)執行Shell指令碼有兩種方式:作為可執行程式和作為直譯器引數
      作為可執行程式,這種方式#!/bin/bash必須要寫,以便讓系統查詢到正確的直譯器,執行之前通過chmod +x ./test.sh使指令碼具有執行許可權; 
      作為直譯器引數,直接執行直譯器,不需要在第一行指定直譯器資訊 /bin/sh test.sh。
      補充:Shell註釋,以“#”開頭的行就是註釋,會被直譯器忽略。如果在開發的過程中遇到大段的程式碼需要註釋起來,過一會又要取消註釋,
        可以將這一大段語句用一對花括號括起來,定義成一個函式。

2、Shell變數的定義、刪除變數、只讀變數、變數型別
  變數是任何一種程式語言都必不可少的組成部分,變數用來存放各種資料。指令碼語言在定義變數時通常不需要指明型別,直接賦值即可。
在Bash shell中,每一個變數的值都是字串,無論給變數賦值的時候有沒有使用引號,值都會以字串的形式存在。
(1)變數定義,支援以下三種方式:
variable=value   variable='value'    variable="value"

注意:賦值號的周圍不能有空格!!!
名命規則:a、變數名由數字、字母、下劃線組成;
b、必須以字母或下劃線開頭;
c、不能使用shell裡的關鍵字(通過help命令可以檢視保留關鍵字)。
說明:variable是變數名,value是賦給變數的值。如果value不包含任何空白符(例如空格、Tab縮排等),那麼可以不適用引號;
如果value包含了空白符,就必須使用引號包圍起來,以單引號‘’包圍變數的值時,單引號裡面是什麼就會輸出什麼,即使內容裡面有變數或者命令也會把它們
原樣輸出,這種方式比較適合定義顯示純字串的情況(不希望解析變數和命令),以雙引號“”包圍變數的值時,輸出時會先解析裡面的變數和命令,這種方式
比較適合字串中附帶有變數和命令並且想將其解析後再輸出的變數定義。
只讀變數:使用readonly命令可以將變數定義為只讀變數,其值不能被改變,eg: name="lilei" readonly name
(2)使用變數,使用一個定義過的變數,只要在變數名前面加美元符號$即可,如:
name="lilei"
echo $name
echo ${name}
說明:變數名外面的花括號{ }是可選的,加不加都行,加花括號是為了幫助直譯器識別變數的邊界,建議給所有變數加上{}。
(3)將命令的結果賦值給變數,常用的方法有以下兩種;
variable=`command` variable=$(command)
第一種使用反引號包圍命令(不建議),第二種方式用$()包圍起來,區分明顯。
eg: log=$(cat log.txt)
echo $log
(4)刪除變數,使用unset可以刪除變數。語法:
unset variable //變數被刪除後不能再次使用,unset命令不能刪除只讀變數。
(5)變數型別,執行shell時,會同時存在三種變數:
a、區域性變數 :區域性變數在指令碼或命令中定義,僅在當前shell例項中有效,其它shell啟動的程式不能訪問區域性變數。
b、環境變數 :所有的程式,包括shell啟動的程式,都能訪問環境變數,有些程式需要環境變數來保證其正常執行。必要的時候shell指令碼也可以定義環境變數。
c、shell變數 :shell變數是由shell程式設定的特殊變數。shell變數中有一部分是環境變數,有一部分是區域性變數,這些變數保證了shell的正常執行。

3、Shell特殊變數:Shell $0, $#, $*,

[email protected], $?, $$和命令列引數
$0 當前指令碼的檔名;
$n 傳遞給指令碼或函式的引數,n代表是一個數字,表示第幾個引數;
$# 傳遞給指令碼或函式的引數個數;
$* 傳遞給指令碼或函式的所有引數;
[email protected] 傳遞給指令碼或函式的所有引數,被雙引號(" ")包含時,與 $* 稍有不同;
$? 上個命令的退出狀態,或函式的返回值;
$$ 當前Shell程序ID,對於Shell指令碼來說就是這些指令碼所在的程序ID。
$* 和 [email protected] 的區別:都表示傳遞給函式或指令碼的所有引數,不被雙引號(" ")包含時,都以"$1" "$2" … "$n" 的形式輸出所有引數。但是當它們被雙引號(" ")包含時,
1"$*" 會將所有的引數作為一個整體,以"$1 $2 … $n"的形式輸出所有引數;"
[email protected]
" 會將各個引數分開,以"$1" "$2" … "$n" 的形式輸出所有引數。

4、Shell替換:shell變數替換,命令替換,轉義字元
(1)命令替換,指Shell可以先執行命令,將輸出結果暫時儲存,在適當的地方輸出。語法:`command`
#!/bin/bash
DATE=`date`
echo "Date is $DATE"
USERS=`who | wc -l`
echo "Logged in user are $USERS"
UP=`date ; uptime`
echo "Uptime is $UP"

輸出結果:Date is Thu Jul 2 03:59:57 MST 2009
Logged in user are 1
Uptime is Thu Jul 2 03:59:57 MST 2009
03:59:57 up 20 days, 14:03, 1 user, load avg: 0.13, 0.07, 0.15

(2)變數替換,變數替換可以根據變數的狀態(是否為空、是否定義等)來改變它的值。
變數替換形式:
$(var) 變數本來的值
$(var;-word) 如果變數var為空或已被刪除(unset),那麼返回word,但不改變var的值。
$(var;=word) 如果變數var為空或已被刪除(unset),那麼返回word,並將var的值設定為word。
$(var:?message) 如果變數var為空或已被刪除(unset),那麼將訊息message送到標準錯誤輸出,可以用來檢測
變數var是否可以被正常賦值。若此替換出現在Shell指令碼中,那麼指令碼將停止執行。
${var:+word} 如果變數 var 被定義,那麼返回 word,但不改變 var 的值。

(3)轉義字元,如果表示式中包含特殊字元,Shell將會進行替換,例如,在雙引號中使用變數就是一種替換,轉義字元也是一種替換。
eg: #!/bin/bash
a=10
echo -e "Value of a is $a \n"
輸出結果:Value of a is 10
補充:-e表示對轉義字元進行替換,如果不使用-e選項,將會原樣輸出:Value of a is 10\n
以下轉義字元都可以在echo中使用:
\\ 反斜槓 \a 警報,響鈴 \b 退格(刪除鍵)
\f 換頁(FF),將當前位置移到下頁開頭 \n 換行
\r 回車 \t 水平製表符(tab鍵) \v 垂直製表符

5、Shell運算子:Shell算術運算子、關係運算符、布林運算子、字串運算子等
Bash支援很多運算子,但是原生bash不支援簡單的數學運算,但是可以通過其他命令實現,例如awk、expr等。
(1)算術運算子,expr是一款表示式計算工具,使用它能完成表示式的求值工作,例如:
兩個數相加
#!/bin/bash
val=`expr 2 + 2`
echo "Total value : $val"
注意:表示式和運算子之間要有空格,例如2+2是不對的,必須寫成2 + 2;
完整的表示式要被``包含,這個符號不是常用的單引號,在Esc下面的符號。

算術運算子列表(a=10,b=20):
運算子 說明 舉例
+ 加法 `expr $a + $b` 結果為30
- 減法 `expr $a - $b` 結果為10
* 乘法 `expr $a \* $b` 結果為200
/ 除法 `expr $b / $a` 結果為2
% 取餘 `expr $b % $a` 結果為0
= 賦值 a=$b 將把變數b的值賦給a
== 相等 用於比較兩個數字,相等則返回true [ $a == $b ]返回false
!= 不相等 用於比較兩個數字,不相等返回true [ $a != $b ]放回true
注意:條件表示式要放在方括號之間,並且要有空格,例如[$a==$b]是錯誤的,必須寫成[ $a == $b ]

(2)關係運算符,關係運算符只支援數字,不支援字串,除非字串的值是數字。
運算子 說明 舉例
-eq 檢測兩個數是否相等,相等返回 true。 [ $a -eq $b ] 返回 true。
-ne 檢測兩個數是否相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 檢測左邊的數是否大於右邊的,如果是,則返回 true。 [ $a -gt $b ] 返回 false。
-lt 檢測左邊的數是否小於右邊的,如果是,則返回 true。 [ $a -lt $b ] 返回 true。
-ge 檢測左邊的數是否大等於右邊的,如果是,則返回 true。 [ $a -ge $b ] 返回 false。
-le 檢測左邊的數是否小於等於右邊的,如果是,則返回 true。 [ $a -le $b ] 返回 true。

(3)布林運算子
運算子 說明 舉例
! 非運算,表示式為 true 則返回 false,否則返回 true。 [ ! false ] 返回 true。
-o 或運算,有一個表示式為 true 則返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a 與運算,兩個表示式都為 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。

(4)字串運算子 a="abc" b="efg"

運算子 說明 舉例
= 檢測兩個字串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 檢測兩個字串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 檢測字串長度是否為0,為0返回 true。 [ -z $a ] 返回 false。
-n 檢測字串長度是否為0,不為0返回 true。 [ -z $a ] 返回 true。
str 檢測字串是否為空,不為空返回 true。 [ $a ] 返回 true。

(5)檔案測試運算子,用於檢測Unix檔案的各種屬性。
例如,變數 file 表示檔案“/var/www/tutorialspoint/unix/test.sh”,它的大小為100位元組,具有 rwx 許可權。下面的程式碼,將檢測該檔案的各種屬性:

操作符 說明 舉例
-b file 檢測檔案是否是塊裝置檔案,如果是,則返回 true。 [ -b $file ] 返回 false。
-c file 檢測檔案是否是字元裝置檔案,如果是,則返回 true。 [ -b $file ] 返回 false。
-d file 檢測檔案是否是目錄,如果是,則返回 true。 [ -d $file ] 返回 false。
-f file 檢測檔案是否是普通檔案(既不是目錄,也不是裝置檔案),如果是,則返回 true。 [ -f $file ] 返回 true。
-g file 檢測檔案是否設定了 SGID 位,如果是,則返回 true。 [ -g $file ] 返回 false。
-k file 檢測檔案是否設定了粘著位(Sticky Bit),如果是,則返回 true。 [ -k $file ] 返回 false。
-p file 檢測檔案是否是具名管道,如果是,則返回 true。 [ -p $file ] 返回 false。
-u file 檢測檔案是否設定了 SUID 位,如果是,則返回 true。 [ -u $file ] 返回 false。
-r file 檢測檔案是否可讀,如果是,則返回 true。 [ -r $file ] 返回 true。
-w file 檢測檔案是否可寫,如果是,則返回 true。 [ -w $file ] 返回 true。
-x file 檢測檔案是否可執行,如果是,則返回 true。 [ -x $file ] 返回 true。
-s file 檢測檔案是否為空(檔案大小是否大於0),不為空返回 true。 [ -s $file ] 返回 true。
-e file 檢測檔案(包括目錄)是否存在,如果是,則返回 true。 [ -e $file ] 返回 true。

6、Shell字串
字串是shell程式設計中最常見最有用的資料型別,字串可以用單引號,也可以用雙引號,也可以不用引號。
a) 單引號: str='this is a string'
注意:單引號裡面的所有字元都會原樣輸出,單引號字串中的變數是無效的;
單引號字串中不能出現單引號。
b) 雙引號:your_name='qinjx'
str="Hello, I know your are \"$your_name\"! \n"
注意:雙引號裡可以有變數,也可以出現轉義字元。
c)拼接字串
your_name="qinjx"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1

d)獲取字串長度
string=“abcd”
echo ${#string} #輸出4

e)提取子字串
string="alibaba is a great company"
echo ${string:1:4} #輸出liba

f)查詢字串
string="alibaba is a great company"
echo `expr index "$string" is`

7、Shell陣列
bash支援一維陣列(不支援多維陣列),並且沒有限定陣列的大小,類似與C語言,陣列元素的下標由0開始編號。獲取
陣列中的元素要利用下標,下標可以是整數或者算術表示式,其值應該大於或等於0。
(1)定義陣列,在Shell中,用括號來表示陣列,陣列元素用“空格”符號分割開。
eg: array_name=(value0 value1 value2)
可以單獨定義陣列的各個分量,可以不使用連續的下標,並且下標的範圍沒有限制:
array_name[0]=value0
array_name[1]=value1
array_name[3]=value3
(2)讀取陣列,其一般格式是:
${array_name[index]}
可以使用@或*獲取陣列的所有元素,例如:
${array_name[*]} 或 ${array_name[@]}
(3)獲取陣列的長度,獲取陣列長度與獲取字串長度的方法相同,例如:
length=${#array_name[@]} 或 length=${#array_name[*]}

8、Shell echo命令
echo是一個Shell的一個內部指令,用於在螢幕上打印出指定的字串。命令格式: echo arg
還可以使用echo實現更復雜的輸出格式控制:
(1) echo "\"It is a test\"" 結果將是:"It is a test" 雙引號也可以省略。
(2) 如果變數與其他字元相連,需要使用大括號({})
mount=8 echo "${mount}-l-2019" 結果將是:4-1-2019
(3) 顯示換行 echo "OK!\n" echo "It is a test"
輸出: OK!
It is a test
(4) 顯示不換行 echo "OK!\c" echo "It is a test"
輸出:OK!It is a test
(5) 顯示結果重定向至檔案
echo "It is a test" > myfile
(6) 原樣輸出字串(不進行轉義),請使用單引號。
eg: echo '$name\"'
(7) 顯示命令執行結果
eg: echo `date` 結果將顯示當前日期
注意:從以上可以看出,雙引號可有可無,單引號主要是用在原樣輸出中。

9、Shell test命令
Shell中的test命令用於檢查某個條件是否成立,它可以進行數值、字元和檔案三個方面的測試。
(1)數值測試
-eq 等於則為真 -ne 不等於則為真 -gt 大於則為真
-ge 大於等於則為真 -lt 小於則為真 -le 小於等於則為真

num1=100,num2=100
if test $[num1] -eq $[num2]
then
echo 'The two numbers are equal!'
else
echo 'The two numbers are not equal!'
fi

輸出:The two numbers are equal!

(2)字串測試
= 等於則為真 != 不等於則為真
-z字串 字串長度偽則為真 -n字串 字串長度不偽則為真

num1=100,num2=100
if test num1=num2
then
echo 'The two strings are equal!'
else
echo 'The two strings are not equal!'
fi

輸出:The two strings are equal!

(3)檔案測試
-e 檔名 如果檔案存在則為真 -r 檔名 如果檔案存在且可讀則為真
-w 檔名 如果檔案存在且可寫則為真 -x 檔名 如果檔案存在且可執行則為真
-s 檔名 如果檔案存在且至少有一個字元則為真 -d 檔名 如果檔案存在且為目錄則為真
-f 檔名 如果檔案存在且為普通檔案則為真 -c 檔名 如果檔案存在且為字元型特殊檔案則為真
-b 檔名 如果檔案存在且為塊特殊檔案則為真

cd /bin
if test -e ./bash
then
echo 'The file already exists!'
else
echo 'The file does not exists!'
fi

輸出:The file already exists!

補充:Shell還提供了與( ! )、或( -o )、非( -a )三個邏輯操作符用於將測試條件連線起來,其優先順序為:“!”最高,“-a”次之,“-o”最低。例如:
cd /bin
if test -e ./notFile -o ./bash
then
echo 'One file exists at least!'
else
echo 'Both dose not exists!'
fi
輸出:One file exists at least!

10、Shell if else命令
if語句通過關係運算符判斷表示式的真假來決定執行哪個分支。Shell有三種if...else語句:
(1)if...fi語句
語法: if [ expression ]
then
Statement(s) to be executed if expression is true
fi
說明:如果expression返回true,then後面的語句將會被執行;如果返回false,不會執行任何語句。
最後必須以fi來閉合if,expression和方括號([])之間必須有空格,否則將會有語法上的錯誤。

(2)if...else...fi語句
語法 if [ expression ]
then
Statement(s) to be executed if expression is true
else
Statement(s) to be executed if expression is not true
fi
說明:如果 expression 返回 true,那麼 then 後邊的語句將會被執行;否則,執行 else 後邊的語句。

(3)if...elif...else...fi語句
語法: if [ expression 1 ]
then
Statement(s) to be executed if expression 1 is true
elif [ expression 2 ]
then
Statement(s) to be executed if expression 2 is true
elif [ expression 3 ]
then
Statement(s) to be executed if expression 3 is true
else
Statement(s) to be executed if no expression is true
fi
說明:哪一個 expression 的值為 true,就執行哪個 expression 後面的語句;如果都為 false,那麼不執行任何語句。

11、Shell for迴圈
for 變數 in 列表
do
command1
command2
command3
done

列表是一組值(數字、字串等)組成的序列,每個值通過空格分隔。每迴圈一次,就將列表中的下一個值賦給變數。
in列表是可選的,如果不用它,for迴圈使用命令列的位置引數。
顯示主目錄下以.bash開頭的檔案:

for FILE in $HOME/.bash*
do
echo $FILE
done

執行結果:
/root/.bash_history
/root/.bash_logout
/root/.bash_profile
/root/.bashrc

13、Shell until迴圈
until迴圈執行一系列命令直至條件為true時停止。until迴圈與while迴圈在處理方式上正好相反。一般while迴圈優先於
until迴圈:

until command
do
Statement(s) to be executed until command is true
done

command 一般為條件表示式,如果返回值為 false,則繼續執行迴圈體內的語句,否則跳出迴圈。

14、Shell函式、函式引數、輸入輸出重定向、shell檔案包含
http://c.biancheng.net/cpp/view/7011.html


shell 正則表示式