title: Shell 編程
tags:shell
- Shell
categories:編程
- Linux
[TOC]數組
注意: 不要將腳本命名爲test
,由於test
是一個內置的應用程序bash
#!/bin/bash # File: hello.sh echo "Hello World !"
bovenson@ThinkCentre:~/Git/neu-ip-gateway-manager$ bash hello.sh Hello World!
定義ssh
v="This is a variable."
注意編程語言
使用函數
使用一個定義過的變量,只要在變量名前面加美圓符號便可工具
#!/bin/bash # File: hello.sh v="This is a variable." echo $v echo ${v} # 變量名外面的花括號是可選的,加不加都行,加花括號是爲了幫助解釋器識別變量的邊界
bovenson@ThinkCentre:~/Tmp$ bash hello.sh This is a variable. This is a variable. bovenson@ThinkCentre:~/Tmp$
變量名外面的花括號是可選的,加不加都行,加花括號是爲了幫助解釋器識別變量的邊界, 推薦給全部變量加上花括號,這是個好的編程習慣, 好比下面這種狀況:oop
for skill in Ada Coffe Action Java; do echo "I am good at ${skill}Script" done
只讀變量測試
使用 readonly 命令能夠將變量定義爲只讀變量,只讀變量的值不能被改變。
#!/bin/bash # File: hello.sh my_name="szk" readonly my_name my_name="bovenson"
bovenson@ThinkCentre:~/Tmp$ bash hello.sh hello.sh:行6: my_name: 只讀變量 bovenson@ThinkCentre:~/Tmp$
刪除變量
unset variable_name
注意:
變量類型
字符串是shell編程中最經常使用最有用的數據類型(除了數字和字符串,也沒啥其它類型好用了),字符串能夠用單引號,也能夠用雙引號,也能夠不用引號。單雙引號的區別跟PHP相似。
str='this is a string'
單引號字符串的限制:
my_name='szk' str="Hello, I know your are \"$my_name\"! \n"
雙引號的優勢:
#!/bin/bash # File: hello.sh my_name="szk" greeting="hello, "$my_name" !" greeting_1="hello, ${my_name} !" echo $greeting $greeting_1
bovenson@ThinkCentre:~/Tmp$ bash hello.sh hello, szk ! hello, szk ! bovenson@ThinkCentre:~/Tmp$
#!/bin/bash # File: hello.sh my_name="szk" echo ${#my_name}
bovenson@ThinkCentre:~/Tmp$ bash hello.sh 3
#!/bin/bash # File: hello.sh slogon="One World, One Dream!" echo ${slogon:4:5} # 這裏4是開始下標, 5是截取長度
bovenson@ThinkCentre:~/Tmp$ bash hello.sh World
#!/bin/bash # File: hello.sh slogon="One World, One Dream!" index=`expr index "$slogon" W` # 查找W字符 echo ${index} index=`expr index "$slogon" Dra` # 查找字符D, r, a中的一個 echo ${index}
bovenson@ThinkCentre:~/Tmp$ bash hello.sh 5 7
假設有變量 var=http://www.aaa.com/123.htm
方法一
# # 號截取,刪除左邊字符,保留右邊字符 echo ${var#*//} # 其中 var 是變量名,# 號是運算符,*// 表示從左邊開始刪除第一個 // 號及左邊的全部字符 # 即刪除 http:// # 結果是 :www.aaa.com/123.htm
方法二
# ## 號截取,刪除左邊字符,保留右邊字符。 echo ${var##*/} # ##*/ 表示從左邊開始刪除最後(最右邊)一個 / 號及左邊的全部字符 # 即刪除 http://www.aaa.com/ # 結果是 123.htm
方法三
# %號截取,刪除右邊字符,保留左邊字符 echo ${var%/*} # %/* 表示從右邊開始,刪除第一個 / 號及右邊的字符 # 結果是:http://www.aaa.com
方法四
# %% 號截取,刪除右邊字符,保留左邊字符 echo ${var%%/*} # %%/* 表示從右邊開始,刪除最後(最左邊)一個 / 號及右邊的字符 # 結果是:http:
方法五
# 從左邊第幾個字符開始,及字符的個數 echo ${var:0:5} # 其中的 0 表示左邊第一個字符開始,5 表示字符的總個數。 # 結果是:http:
方法六
# 從左邊第幾個字符開始,一直到結束 echo ${var:7} # 其中的 7 表示左邊第8個字符開始,一直到結束 # 結果是 :www.aaa.com/123.htm
方法七
# 從右邊第幾個字符開始,及字符的個數 echo ${var:0-7:3} # 其中的 0-7 表示右邊算起第七個字符開始,3 表示字符的個數。 # 結果是:123
方法八
# 從右邊第幾個字符開始,一直到結束 echo ${var:0-7} # 表示從右邊第七個字符開始,一直到結束。 # 結果是:123.htm
注:
定義數組
在Shell中,用括號來表示數組,數組元素用"空格"符號分割開:
數組名=(值1 值2 ... 值n)
例如:array_name=(value0 value1 value2 value3)
或者:
array_name=( value0 value1 value2 value3 )
還能夠單獨定義數組的各個份量:
array_name[0]=value0 array_name[1]=value1 . . . array_name[n]=valuen
讀取數組
讀取數組元素值的通常格式是:
${數組名[下標]}
例如:
valuen=${array_name[n]}
使用@符號能夠獲取數組中的全部元素,例如:
echo ${array_name[@]}
#!/bin/bash # File: hello.sh slogon=("One" "World" "," "One" "Dream!") echo ${slogon[0]} echo ${slogon[1]} echo ${slogon[@]}
bovenson@ThinkCentre:~/Tmp$ bash hello.sh One World One World , One Dream! bovenson@ThinkCentre:~/Tmp$
獲取數組長度
#!/bin/bash # File: hello.sh slogon=("One" "World" "," "One" "Dream!") # 獲取數組長度的方法與獲取字符串長度的方法相同 echo ${#slogon[@]} echo ${#slogon[*]}
bovenson@ThinkCentre:~/Tmp$ bash hello.sh 5 5
示例:
#-------------------------------------------- # 這是一個註釋 # author:菜鳥教程 # site:www.runoob.com # slogan:學的不只是技術,更是夢想! #-------------------------------------------- ##### 用戶配置區 開始 ##### # # # 這裏能夠添加腳本描述信息 # # ##### 用戶配置區 結束 #####
每一行加個#符號太費力了,能夠把這一段要註釋的代碼用一對花括號括起來,定義成一個函數,沒有地方調用這個函數,這塊代碼就不會執行,達到了和註釋同樣的效果.
位置參數
咱們能夠在執行 Shell 腳本時,向腳本傳遞參數,腳本內獲取參數的格式爲:$n。n 表明一個數字,1 爲執行腳本的第一個參數,2 爲執行腳本的第二個參數,以此類推……
位置參數包括命令名和命令行參數.在shell腳本中, 按照它們在命令行上的位置來引用它們(如命令command a b c
中參數a
,b
,c
的位置 ). 不能經過賦值語句改變位置參數的值.
bash的內置命令set
能夠修改除調用程序名(命令名)之外的任意位置參數, 可是在tcsh中, set
內置命令不能改變位置參數的值
在腳本中使用 $0 $1 來獲取位置參數
#!/bin/bash # File: hello.sh echo "Shell 傳遞參數實例!"; echo "執行的文件名:$0"; echo "第一個參數爲:$1"; echo "第二個參數爲:$2"; echo "第三個參數爲:$3";
bovenson@ThinkCentre:~/Tmp$ bash hello.sh v1 v2 v3 v4 v5 v6 v7 Shell 傳遞參數實例! 執行的文件名:hello.sh 第一個參數爲:v1 第二個參數爲:v2 第三個參數爲:v3 bovenson@ThinkCentre:~/Tmp$
幾個特殊字符用來處理參數
字符 | 說明 |
---|---|
$# |
傳遞到腳本的參數個數 |
$* |
以一個單字符串顯示全部向腳本傳遞的參數。如$* 用" 括起來的狀況、以$1 $2 … $n 的形式輸出全部參數。 |
$$ |
腳本運行的當前進程ID號 |
$! |
後臺運行的最後一個進程的ID號 |
$@ |
與$* 相同,可是使用時加引號,並在引號中返回每一個參數。如$@ 用" 括起來的狀況、以$1 $2 … $n 的形式輸出全部參數。 |
$- |
顯示Shell使用的當前選項,與set命令功能相同。 |
$? |
顯示最後命令的退出狀態。0表示沒有錯誤,其餘任何值代表有錯誤。 |
#!/bin/bash # File: hello.sh echo "Shell 傳遞參數實例!"; echo "第一個參數爲:$1"; echo "參數個數爲:$#"; echo "傳遞的參數做爲一個字符串顯示:$*";
bovenson@ThinkCentre:~/Tmp$ bash hello.sh v1 v2 v3 v4 v5 v6 v7 Shell 傳遞參數實例! 第一個參數爲:v1 參數個數爲:7 傳遞的參數做爲一個字符串顯示:v1 v2 v3 v4 v5 v6 v7
$*
與 $@
區別
原生bash不支持簡單的數學運算,可是能夠經過其餘命令來實現,例如 awk 和 expr,expr 最經常使用。
expr 是一款表達式計算工具,使用它能完成表達式的求值操做。例如,兩個數相加(注意使用的是反引號 ` 而不是單引號 '):
#!/bin/bash val=`expr 2 + 2` echo "兩數之和爲 : $val"
運算符 | 說明 | 舉例 |
---|---|---|
+ | 加法 | `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 |
注意:
運算符 | 說明 |
---|---|
-eq | 檢測兩個數是否相等,相等返回 true |
-ne | 檢測兩個數是否相等,不相等返回 true |
-gt | 檢測左邊的數是否大於右邊的,若是是,則返回 true |
-lt | 檢測左邊的數是否小於右邊的,若是是,則返回 true |
-ge | 檢測左邊的數是否大於等於右邊的,若是是,則返回 true |
-le | 檢測左邊的數是否小於等於右邊的,若是是,則返回 true |
運算符 | 說明 |
---|---|
! | 非運算,表達式爲 true 則返回 false,不然返回 true |
-o | 或運算,有一個表達式爲 true 則返回 true |
-a | 與運算,兩個表達式都爲 true 才返回 true |
運算符 | 說明 | ||
---|---|---|---|
&& | 邏輯的 AND | ||
\ | \ | 邏輯的 OR |
運算符 | 說明 |
---|---|
= | 檢測兩個字符串是否相等,相等返回 true |
!= | 檢測兩個字符串是否相等,不相等返回 true |
-z | 檢測字符串長度是否爲0,爲0返回 true |
-n | 檢測字符串長度是否爲0,不爲0返回 true |
str | 檢測字符串是否爲空,不爲空返回 true, 如 [ $a ] |
文件測試運算符用於檢測 Unix 文件的各類屬性
操做符 | 說明 | 舉例 |
---|---|---|
-b file | 檢測文件是不是塊設備文件,若是是,則返回 true。 | [ -b $file ] 返回 false。 |
-c file | 檢測文件是不是字符設備文件,若是是,則返回 true。 | [ -c $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。 |
if test-command then comands fi
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi
if condition then command1 command2 ... commandN else command fi
if condition1 then command1 elif condition2 then command2 else commandN fi
for var in item1 item2 ... itemN do command1 command2 ... commandN done
for var in item1 item2 ... itemN; do command1; command2… done;
# 示例 1 for loop in 1 2 3 4 5 do echo "The value is: $loop" done # 輸出 The value is: 1 The value is: 2 The value is: 3 The value is: 4 The value is: 5 # 示例 2 for str in 'This is a string' do echo $str done # 輸出 This is a string
while condition do command done
# 示例 1 #!/bin/sh int=1 while(( $int<=5 )) do echo $int let "int++" done # 輸出 1 2 3 4 5 # 示例 2 echo '按下 <CTRL-D> 退出' echo -n '輸入你最喜歡的電影名: ' while read FILM do echo "是的!$FILM 是一部好電影" done
while : do command done # 或者 while true do command done # 或者 for (( ; ; ))
until condition do command done # 條件可爲任意測試條件,測試發生在循環末尾,所以循環至少執行一次—請注意這一點
case 值 in 模式1) command1 command2 ... commandN ;; 模式2) command1 command2 ... commandN ;; esac # case的語法和C family語言差異很大,它須要一個esac(就是case反過來)做爲結束標記 # 每一個case分支用右圓括號,用兩個分號表示break。
在循環過程當中,有時候須要在未達到循環結束條件時強制跳出循環,Shell使用兩個命令來實現該功能:break和continue。
shell中函數的定義格式以下:
[ function ] funname [()] { action; [return int;] }
# 示例 1 demoFun(){ echo "這是個人第一個 shell 函數!" } echo "-----函數開始執行-----" demoFun echo "-----函數執行完畢-----" # 示例 2 funWithReturn(){ echo "這個函數會對輸入的兩個數字進行相加運算..." echo "輸入第一個數字: " read aNum echo "輸入第二個數字: " read anotherNum echo "兩個數字分別爲 $aNum 和 $anotherNum !" return $(($aNum+$anotherNum)) } funWithReturn echo "輸入的兩個數字之和爲 $? !"
命令 | 說明 |
---|---|
command > file | 將輸出重定向到 file。 |
command < file | 將輸入重定向到 file。 |
command >> file | 將輸出以追加的方式重定向到 file。 |
n > file | 將文件描述符爲 n 的文件重定向到 file。 |
n >> file | 將文件描述符爲 n 的文件以追加的方式重定向到 file。 |
n >& m | 將輸出文件 m 和 n 合併。 |
n <& m | 將輸入文件 m 和 n 合併。 |
<< tag | 將開始標記 tag 和結束標記 tag 之間的內容做爲輸入。 |
須要注意的是文件描述符 0 一般是標準輸入(STDIN),1 是標準輸出(STDOUT),2 是標準錯誤輸出(STDERR)。