界定程序執行環境;(本質是斷定程序是否執行)node
(1) 根據運行的命令的狀態結果斷定;
例如 id root &>/dev/null 等
(2) 測試表達式
test EXPRESSION
[ EXPRESSION ]
` EXPRESSION `(建議多多使用此[[]],測試表達式和[]必須有空格)git
整數測試:隱含着作數值大小比較,因此不要給變量引用加引用;
$A -gt $B:是否大於;是則爲「真」,不然爲「假」;
$A -ge $B: 是否大於等於;
$A -lt $B:是否小於;
$A -le $B: 是否小於等於;
$A -eq $B: 是否等於;
$A -ne $B:是否不等於;bash
字符串測試:ASCII數值越大,字符比較時其值越大;
"$A" > "$B":是否大於;
"$A" < "$B":是否小於;
"$A" == "$B":是否等於;
"$A" != "$B":是否不等於;
-z "$A":是否爲空;空則爲「真」,不然爲「假」
-n "$A":是否不空;不空則「真」,空則爲「假」ide
若是首字符相同則比較第二個字符以此類推
注意:應該使用` EXPRESSION `測試
文件測試:測試文件的存在性以及屬性;
-e $file: 是否存在;存在則爲「真」,不然爲「假」;
-a $file: 同上;
-f $file:文件是否存在且爲普通文件;
-d $file:文件是否存在且爲目錄;
-h $file:是否存在且爲符號連接文件;
-L $file: 同上
-b $file:是否存在且爲塊設備文件;
-c $file:是否存在且爲字符設備文件;
-S $file:是否存在且爲套接字文件;
-p $file: 是否存在且爲管道文件;spa
-r $file: 當前用戶對文件是否擁有讀權限;
-w $file:當前用戶對文件是否擁有寫權限;
-x $file:當前用戶對文件是否擁有執行權限;rest
-u $file:文件是否擁有SUID權限;
-g $file:文件是否擁有SGID權限;
-k $file:文件是否擁有sticky權限;ci
-O $file: 當前用戶是否爲指定文件的屬主;
-G $file: 當前用戶是否爲指定文件的屬組;字符串
雙目操做符:
$file1 -nt $file2: file1是否新於file2, file1的最近一次的修改時間戳是否晚於file2 的;
$file1 -ot $file2: file1是否舊於file2, file1的最近一次的修改時間戳是否早於file2 的;
$file1 -ef $file2:file1與file2是否指向了同一個inode;測試兩者是否爲同一個文件 的硬連接;it
bash之條件判斷(選擇執行):
if/then, caseif CONDITION; then
if-true-分支(condition斷定爲真執行該段)
fiif CONDITION; then
if-true-分支
else
if-false-分支(condition斷定爲假執行該段)
fi! CONDITION: 取反
練習:寫一個腳本
若是某路徑不存在,則將其建立爲目錄;不然顯示其存在,並顯示內容類型;#!/bin/bash # filename="/tmp/x/y/z/testdir" if [ -e $filename ]; then ##斷定變量filename的變量值是否存在 echo "$filename exists." file $filename ##存在則執行以上兩行操做 else ##不存在執行以下操做 mkdir -p $filename fi練習:寫一個腳本,完成以下功能;
判斷給定的兩個數值,孰大孰小;
給定數值的方法:腳本參數,命令交互;#!/bin/bash # read -p "Plz enter two integer: " -t 10 num1 num2 ##與用戶以交互方式 賦值變量num1 變量num2 if [ -z "$num1" ]; then echo "Plz give two integers." exit 1 ##斷定第一個參數是否爲空 是則提示並退出腳本 fi if [ -z "$num2" ]; then echo "Plz give tow integers." exit 1 ##斷定第一個參數是否爲空 是則提示並退出腳本 fi if [ $num1 -ge $num2 ]; then ##斷定變量num1的變量值是否大於變量num2的變量值 echo "Max: $num1, Min: $num2." ##變量num1大則執行此命令 else echo "Max: $num2, Min: $num1." ##變量num1小則執行此命令 fi多分支的if語句:
單分支:
if CONDITION; then
if-true-分支
fi雙分支:
if CONDITION; then
if-true-分支 ()
else
if-false-分支
fi多分支:用於須要對多種狀況斷定是否執行時使用
if CONDITION1; then
if-CONDITION1-true-分支
elif CONDTION2; then
if-CONDITIO2-true-分支
...
else
if-ALL-false-分支
fi示例:經過腳本參數傳遞一個文件路徑給腳本,判斷其類型;(文件只會符合一個斷定條件)
#!/bin/bash # if [ $# -lt 1 ]; then echo "Usage: $0 <path>" exit 1 fi ##以上檢測至少要有一個參數傳遞給腳本 不然腳本結束 if [ -f $1 ]; then echo "Rgular file." ##傳遞的第一個參數是存在並且是普通文件 elif [ -d $1 ]; then echo "Directory." ##傳遞的第一個參數是存在並且是目錄文件 elif [ -h $1 ]; then echo "Symbolic link." ##傳遞的第一個參數是存在並且是符號連接文件 elif [ -b $1 ]; then echo "Block special." ##傳遞的第一個參數是存在並且是塊文件 elif [ -c $1 ]; then echo "Charactoer special." ##傳遞的第一個參數是存在並且是字符文件 elif [ -S $1 ]; then echo "Socket file." ##傳遞的第一個參數是存在並且是套接字文件 else echo "file not exist or unknown type." ##以上斷定都不是則執行此命令 fi
示例:腳本可接受四個參數
start: 建立文件/var/lock/subsys/SCRIPT_NAME
stop: 刪除此文件
restart: 刪除此文件並從新建立
status: 若是文件存在,顯示爲"running",不然,顯示爲"stopped"basename命令:
取得路徑的基名;#!/bin/bash # prog=$(basename $0) ##取得腳本路徑的基名賦值給變量prog lockfile="/var/lock/subsys/$prog" ##生產新的路徑賦值給變量lockfile #echo $lockfile if [ $# -lt 1 ]; then echo "Usage: $prog start|stop|restart|status" exit 1 fi ##斷定必須有至少一個參數傳遞給腳本 if [ "$1" == "start" ]; then if [ -f $lockfile ]; then echo "$prog is started yet." ##斷定傳遞來的參數是start 且$lockfile是普通文件則顯示腳本is started yet else touch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..." ##斷定傳遞來的參數是start 且$lockfile不存在,則建立$lockfile文件建立成功後顯示Starting $prog ok.,若是建立失敗則顯示啓動失敗 fi elif [ "$1" == 'stop' ]; then if [ -f $lockfile ]; then rm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..." ##斷定傳遞來的參數是stop且$lockfile是普通文件則強制刪除$lockfile刪除成功後顯示Stop $prog ok....",若是刪除失敗則顯示中止失敗 else echo "$prog is stopped yet." ##斷定傳遞來的參數是stop且$lockfile不存在則顯示$prog(取變量值 )is stopped yet fi elif [ "$1" == 'restart' ]; then if [ -f $lockfile ]; then rm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..." ##斷定傳遞來的參數是restart且$lockfile是普通文件則強制刪除$lockfile刪除成功後建立新的$lockfile,建立成功後顯示Restarting $porg ok else touch $lockfile && echo "$prog is stopped, Starting $prog ok...." ##斷定傳遞來的參數是restart且$lockfile不存在則建立新的$lockfile,建立成功後顯示$prog is stopped, Starting $prog ok fi elif [ "$1" == 'status' ]; then if [ -f $lockfile ]; then echo "Running..." ##斷定傳遞來的參數是status且$lockfile是普通文件則顯示正在運行 else echo "Stopped..." ##斷定傳遞來的參數是status且$lockfile不存在則顯示已經中止 fi else echo "Usage: $prog start|stop|restart|sttus" exit 1 ##斷定如傳遞來的參數不是start|stop|restart|sttus,則提示Usage: $prog start|stop|restart|sttus,而後錯誤結束腳本 fi
case語句
簡潔版多分支if語句;
使用場景:判斷某變量的值是否爲多種情形中的一種時使用;語法:
case $VARIABLE in
PATTERN1)
分支1
;; ##斷定$VARIABLE符合PATTERN1則執行分支1命令PATTERN2)
分支2
;; ##斷定$VARIABLE符合PATTERN2則執行分支2命令
PATTERN3)
分支3
;; ##斷定$VARIABLE符合PATTERN3則執行分支3命令
...
*)
分支n
;; ##斷定$VARIABLE符合PATTERNn則執行分支n命令
esacPATTERN可以使用glob模式的通配符:
*: 任意長度的任意字符;
?: 任意單個字符;
[]: 指定範圍內的任意單個字符;
a|b: 多選1;示例:提示鍵入任意一個字符;判斷其類型;
#!/bin/bash # read -p "Plz enter a character: " char ##提示輸入一個字符 用交互方式複製給變量char case $char in [a-z]) ##輸入的爲一個字母則顯示爲字母 echo "A character." ;; [0-9]) echo "A digit." ##輸入的爲一個數字則顯示爲數字 ;; *) echo "A special character." ##若是以上匹配不到,且輸入的是任意長度的任意字符則顯示爲特殊字符 ;; esac
示例:腳本可接受四個參數
start: 建立文件/var/lock/subsys/SCRIPT_NAME
stop: 刪除此文件
restart: 刪除此文件並從新建立
status: 若是文件存在,顯示爲"running",不然,顯示爲"stopped"#!/bin/bash # prog=$(basename $0) lockfile="/var/lock/subsys/$prog" #echo $lockfile if [ $# -lt 1 ]; then echo "Usage: $prog start|stop|restart|status" exit 1 fi case $1 in start) if [ -f $lockfile ]; then echo "$prog is started yet." ##斷定傳遞來的參數是start 且$lockfile是普通文件則顯示腳本is started yet else touch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..." ##斷定傳遞來的參數是start 且$lockfile不存在,則建立$lockfile文件建立成功後顯示Starting $prog ok.,若是建立失敗則顯示啓動失敗 fi ;; stop) if [ -f $lockfile ]; then rm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..." ##斷定傳遞來的參數是stop且$lockfile是普通文件則強制刪除$lockfile刪除成功後顯示Stop $prog ok....",若是刪除失敗則顯示中止失敗 else echo "$prog is stopped yet." ##斷定傳遞來的參數是stop且$lockfile不存在則顯示$prog(取變量值 )is stopped yet fi ;; restart) if [ -f $lockfile ]; then rm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..." ##斷定傳遞來的參數是restart且$lockfile是普通文件則強制刪除$lockfile刪除成功後建立新的$lockfile,建立成功後顯示Restarting $porg ok else touch $lockfile && echo "$prog is stopped, Starting $prog ok...." ##斷定傳遞來的參數是restart且$lockfile不存在則建立新的$lockfile,建立成功後顯示$prog is stopped, Starting $prog ok fi ;; status) if [ -f $lockfile ]; then echo "Running..." ##斷定傳遞來的參數是status且$lockfile是普通文件則顯示正在運行 else echo "Stopped..." ##斷定傳遞來的參數是status且$lockfile不存在則顯示已經中止 fi ;; *) echo "Usage: $prog start|stop|restart|sttus" exit 1 ##斷定如傳遞來的參數不是start|stop|restart|sttus,則提示Usage: $prog start|stop|restart|sttus,而後錯誤結束腳本 esac
for, while, until
循環:將循環體代碼執行0、1或屢次;
進入條件:進入循環的條件;
退出條件:循環終止的條件;
格式:
for VARIABLE in LIST; do
循環體
done
LIST:是由一個或多個空格或換行符分隔開的字符串組成;
把列表的每一個字符串逐個賦值給VARIABLE表示的變量;
for username in user1 user2 user3; do
循環體
done
進入條件:列表非空;
退出條件:列表遍歷結束;
添加10個用戶,user1-user10;
#!/bin/bash # for username in user1 user2 user3 user4 user5; do ##循環進入標記列表仍有能夠賦值,結束條件爲列表參數所有賦值過 if id $username &> /dev/null; then echo "$username exists." else useradd $username echo "Add user $username finished." fi done
LIST的生成方法:
(1) 整數列表
(a) {start..end}
(b) $(seq [start `step` end)
(2) 直接給出列表 例如for username in user1 user2 user3 user4 user5
(3) glob (bash通配)例如 for file in /etc/f*
(4) 命令生成 for file in $(ls /mnt)
示例:數值列表
#!/bin/bash # for i in {1..10}; do ##直接給出列表 if id user$i &> /dev/null; then echo "user$i exists." else useradd user$i echo "Add user user$i finished." fi done
示例:glob
#!/bin/bash # for filename in /var/log/*; do ##輪值爲/var/log下的全部文件 file $filename done
示例:命令生成列表
#!/bin/bash # for username in $(cut -d: -f1 /etc/passwd); do ##命令引用取列表爲系統中的全部用戶 echo "$username primary group: $(id -n -g $username)." done
示例:求100之內因此正整數之和;
#!/bin/bash # declare -i sum=0 for i in {1..100}; do 變量i的變量值輪1到100 sum=$[$sum+$i] ##將變量sum的變量值加上變量i的變量值所得值再從新賦值變量sum done echo $sum
示例:顯示/etc目錄下全部普通文件列表,然後統計一共有多少個文件;
#!/bin/bash # declare -i count=0 ##定義計數器 整型變量count for file in /etc/*; do ##使用通配方法生產/etc文件目錄下的文件列表 if [ -f $file ]; then let count++ ##當是普通文件時計數器變量count本身+1 echo "$count $file" fi done echo "Total: $count files."
示例:寫一個腳本實現以下功能;
獲取當前主機的主機名;
若是當前主機的主機名爲空,或者爲localhost,則將其修改成www.magedu.com
#!/bin/bash # hostname=$(hostname) ##命令引用取得命令執行結果賦值給變量hostname if [ -z "$hostname" -o "$hostname" == "localhost" ]; then ##或表達式組合運用 hostname www.magedu.com fi
練習:寫一個腳本,打印九九乘法表;
循環嵌套
1X1=1
1X2=2 2X2=4
1X3=3 2X3=6 3X3=9
#!/bin/bash # for j in {1..9}; do for i in $(seq 1 $j); do ##雙循環嵌套使用 保證被乘數不得大於乘數 echo -n -e "${i}X${j}=$[$i*$j]\t" done echo done
循環語句:for, while, until
while循環:
while CONDTION; do
循環體
done
進入條件:當CONDITION爲「真」;
退出條件:當CONDITION爲「假」;
while CONDITION; do
循環體
控制變量的修正表達式 (若是沒有修正變量可能會死循環)
done
示例:求100之內全部正整數之和;
#!/bin/bash # declare -i sum=0 declare -i i=1 while [ $i -le 100 ]; do let sum+=$i let i++ done echo "Sum: $sum."
練習:分別求100之內全部奇數之和,及全部偶數之和;
#!/bin/bash # declare -i sum1=0 declare -i sum2=0 declare -i i=0 while [ $i -le 100 ]; do if [ $[${i}%2] -eq 0 ]; then let sum1+=$i else let sum2+=$i fi let i++ done echo "qishu sum $sum2" echo "oushu sum $sum1"
示例:打印九九乘法表
#!/bin/bash # declare -i i=1 declare -i j=1 while [ $j -le 9 ]; do while [ $i -le $j ]; do echo -e -n "${i}X${j}=$[$i*$j]\t" let i++ done echo let i=1 let j++ done
unitl循環:
until CONDITION; do
循環體
循環控制變量的修正表達式
done
進入條件:當CONDITION爲「假」時
退出條件:當CONDITION爲「真」時
示例:求100之內全部正整數之和
#!/bin/bash # declare -i sum=0 declare -i i=1 until [ $i -gt 100 ]; do let sum+=$i let i++ done echo "Sum: $sum."
練習1:分別求100之內全部偶數之和,以及全部奇數之和;
#!/bin/bash # declare -i sum1=0 declare -i sum2=0 declare -i i=0 until [ $i -gt 100 ]; do if [ $[${i}%2] -eq 0 ]; then let sum1+=$i else let sum2+=$i fi let i++ done echo "qishu sum $sum2" echo "oushu sum $sum1"
練習2:實現九九乘法表;
#!/bin/bash # #!/bin/bash # declare -i i=1 declare -i j=1 until [ $i -gt 9 ]; do until [ $j -gt $i ]; do echo -n "${j}x${i}=$[$j*$i] " let j++ done let j=1 let i++ echo done
練習3:分別使用while和until循環實現添加10個用戶:user1-user10;
#!/bin/bash # declare -i i=1 while [ $i -le 10 ]; do useradd user${i} let i++ done
#!/bin/bash # declare -i i=1 until [ $i -gt 10 ];do useradd user${i} let i++ done
循環控制:
continue [n]:提早結束本輪循環,而直接進入下一輪;
break [n]:提早結束循環;
while循環:
while CONDITION; do
.......
if CONDITION2; then
break [n]
fi
done
while CONDITION; do
......
if CONDITION2; then
continue [n]
fi
......
done
示例:求100之內全部偶數之和;
#!/bin/bash # declare -i sum=0 declare -i i=0 while [ $i -le 100 ]; do let i++ if [ $[$i%2] -eq 1 ]; then echo "$i is a odd." continue fi let sum+=$i done echo "Sum: $sum."
死循環:
while true; do
循環體
if CONDTION; then
break
fi
done
until false; do
循環體
if CONDITION; then
break
fi
done
示例:每隔3秒鐘查看當前系統上是否有名爲「gentoo」的用戶登陸;
若是某次查看gentoo登陸了,則顯示gentoo已經登陸;
若是未登陸,就顯示仍然將來,並顯示這是已是第多少次查看了;
#!/bin/bash # username=$1 declare -i count=0 while true; do if who | grep "^$username" &> /dev/null; then echo "$username is logged." break else let count++ echo "$count $username is not login." fi sleep 3 done
#!/bin/bash # declare -i count=0 username=$1 if [ $# -lt 1 ]; then echo "At lease one argument." exit 1 fi if ! id $username &> /dev/null; then echo "No such user." exit 2 fi until who | grep "^$username" &> /dev/null; do let count++ echo "$count $username is not login." sleep 3 done echo "$username is logged on."
while循環的特殊用法:
遍歷文件的每一行:
while read VARIABLE; do
循環體
done < /PATH/FROM/SOME_FILE
示例:找出UID爲偶數的全部用戶,顯示其用戶名和ID號;
#!/bin/bash # while read line; do userid=$(echo $line | cut -d: -f3) if [ $[$userid%2] -eq 0 ]; then echo $line | cut -d: -f1,3 fi done < /etc/passwd
for循環的特殊用法:
for ((expr1;expr2;expr3)); do
循環體
done
expr1: 定義控制變量,並初始賦值;
expr2: 循環控制條件;
進入條件:控制條件爲「真」
退出條件:控制條件爲「假」
expr3: 修正控制變量
示例:求100之內全部正整數之和;
#!/bin/bash # declare -i sum=0 for ((i=1;i<=100;i++)); do let sum+=$i done echo "Sum: $sum."
練習1:打印九九乘法表;
#!/bin/bash # for (( i=1;i<10;i++));do for (( j=1;j<=i;j++));do echo -n "${j}x$i=$[ $j*$i ] " done echo done
練習2:傳遞一個文本文件爲參數給腳本,取出此文件的全部的偶數行給予顯示,行前要顯示行號;
#!/bin/bash # if [ $# -lt 1 ]; then echo " must ernter /path/to/somefile " exit 1 fi j=$(wc -l $1 | cut -d" " -f1 ) if [ -f $1 ]; then for (( i=1;i<=j ;i++ ));do if [ $[${i}%2] -eq 0 ];then echo -n "$i " head -$i $1 | tail -1 fi done fi