在前幾天的的文章中,《[原創]Shell腳本大量示例,你會幾個?》、《[原創]Shell腳本生產示例,你努力學習了嗎?》給大家講解了shell腳本基礎和shell編程的大量實例,如需要查看歷史文章,請點擊公衆號的【文章導航】→
[shell系列文章]查閱,我們在今天的文章中,繼續爲大家帶來shell腳本編程講解!
一、case語句用法演示
case的一個有效用法是提示用戶響應以決定是否繼續進程。這裏提示輸入y以繼續處理,n退出。如果用戶輸入Y、y或yes,處理繼續執行case語句後面部分。如果用戶輸入N、n或no或其他響應,用戶退出腳本。
#!/bin/sh
# caseans.sh
echo -n "Do you wish to proceed [y..n] :"
read ANS
case $ANS in
y|Y|yes|Yes) echo "yes is selected"
;;
n|N) echo "no is selected"
exit 0 # no error so only use exit 0 to terminate
;;
*) echo "`basename $0` : Unknow response" >&2
exit 1
;;
esac
# if we are here then a y|Y|yes|Yes was selected only.
運行腳本,輸入無效響應,得結果:
[root@localhost ~]# ./caseans.sh
Do you wish to proceed [y..n] :df
caseans.sh : Unknow response
給出有效響應:
[root@localhost ~]# ./caseans.sh
Do you wish to proceed [y..n] :y
yes is selected
二、case與命令參數傳遞
可以使用case控制到腳本的參數傳遞。下面腳本中,測試特定變量$#,它包含傳遞的參數個數,如果不等於1,退出並顯示可用信息。然後case語句捕獲下列參數:
passwd、start、stop或help,相對於每一種匹配模式執行進一步處理腳本。如果均不匹配,顯示可用信息到標準錯誤輸出。
#!/bin/sh
# caseparam.sh
if [ $# != 1 ]; then
echo "Usage:`basename $0`[start|stop|help]" >&2
exit 1
fi
# assign the parameter to the variable OPT
OPT=$1
case $OPT in
start) echo "starting.. `basename $0`"
# code here to start a process
;;
stop) echo "stopping.. `basename $0`"
# code here to stop a process
;;
help)
# code here to display a help page
;;
*) echo "Usage:`basename $0`[start|stop|help]"
;;
esac
運行腳本,輸入無效參數:
[root@localhost ~]# ./caseparam.sh what
Usage:caseparam.sh[start|stop|help]
輸入有效參數,結果爲:
[root@localhost ~]# ./caseparam.sh stop
stopping.. caseparam.sh
三、case語句捕獲輸入並執行空命令
不一定要在匹配模式後加入命令,如果你原本不想做什麼,只是在進一步處理前過濾出意外響應,這樣做是一種好辦法。如果要運行對應於一個會計部門的帳目報表,必須首先在決定運行報表的類型前確認用戶輸入一個有效的部門號,匹配所有可能值,其他值無效。用case可以很容易實現上述功能。下面的腳本中如果用戶輸入部門號不是234、453、655或454,用戶退出並返回可用信息。一旦響應了用戶的有效部門號,腳本應用同樣的技術取得報表類型,在case語句末尾顯示有效的部門號和報表類型.
#!/bin/sh
# casevaild.sh
echo -n "Enter the account dept No: :"
read ACC
case $ACC in
234);;
453);;
655);;
454);;
*) echo "`basename $0`: Unknown dept No:" >&2
echo "try ... 234,453,655,454"
exit 1
;;
esac
# if we are here, then we have validated the dept no
echo "1 . post"
echo "2 . prior"
echo -n "Enter the type of report:"
read ACC_TYPE
case $ACC_TYPE in
1) TYPE=post
;;
2) TYPE=prior;;
*) echo "`basename $0`: Unknown account type." >&2
exit 1
;;
esac
# if we are here the we are validated!
echo "now running report for dept $ACC for the type $TYPE"
# run the command reprot...
輸入有效部門號,該腳本不同運行輸入情況的顯示結果:
[root@localhost ~]# ./casevalid.sh
Enter the account dept No: :234
1 . post
2 . prior
Enter the type of report:2
now running report for dept 234 for the type prior
輸入無效部門號,該腳本不同運行輸入情況的顯示結果:
[root@localhost ~]# ./casevalid.sh
Enter the account dept No: :432
casevalid.sh: Unknown dept No:
try ... 234,453,655,454
輸入無效的報表類型,該腳本不同運行輸入情況的顯示結果:
[root@localhost ~]# ./casevalid.sh
Enter the account dept No: :655
1 . post
2 . prior
Enter the type of report:4
casevalid.sh: Unknown account type.
四、使用case語句實現缺省變量值設定
如果在讀變量時輸入回車鍵,不一定總是退出腳本。可以先測試是否已設置了變量,如果未設置,可以設置該值。下面的腳本中,要求用戶輸入運行報表日期。如果用戶輸入回車鍵,則使用缺省日期星期六,並設置爲變量when的取值。如果用戶輸入另外一天,這一天對於case語句是運行的有效日期,即星期六、星期四、星期一。注意,這裏結合使用了日期縮寫作爲捕獲的可能有效日期。
#!/bin/sh
# caserep.sh
echo " Weekly Report"
echo -n "What day do you want to run report [Saturday] :"
# if just a return is hit then except default which is Saturday
read WHEN
echo "validating .. ${WHEN:="Saturday"}"
case $WHEN in
Monday|MONDAY|mon)
;;
Sunday|SUNDAY|sun)
;;
Saturday|SATURDAY|sat)
;;
*)
echo "Are you nuts! this report can only be run on " >&2
echo " on a Saturday, Sunday or Monday" >&2
exit 1
;;
esac
echo "Report to run on $WHEN"
# command here to submitted actual report run
對於正確輸入,執行結果如下:
[root@localhost ~]# ./caserep.sh
Weekly Report
What day do you want to run report [Saturday] :
validating .. Saturday
Report to run on Saturday
對於錯誤的輸入,執行結果如下:
[root@localhost ~]# ./caserep.sh
Weekly Report
What day do you want to run report [Saturday] :Tuesday
validating .. Tuesday
Are you nuts! this report can only be run on
on a Saturday, Sunday or Monday
五、簡單的for循環
此例僅顯示列表1
2 3 4 5,用變量名訪問列表
#!/bin/sh
# for_i.sh
for loop in 1 2 3 4 5
do
echo $loop
done
運行上述腳本,輸出:
[root@localhost ~]# ./for_i.sh
1
2
3
4
5
六、使用for語句打印字符串列表
下面for循環中,列表包含字符串“orange
red blue
grey”,命令爲echo,變量名爲loop,echo命令使用$loop反饋出列表中所有取值,直至列表爲空。
#!/bin/sh
# forlist.sh
for loop in "orange red blue grey"
do
echo "$loop"
done
腳本執行結果:
[root@localhost ~]# ./forlist.sh
orange red blue grey
七、for循環遍歷目錄下的文件
對for循環使用ls命令這個循環執行ls命令,打印當前目錄下所有文件
#!/bin/sh
# forls.sh
for loop in `ls `
do
echo $loop
done
腳本執行結果如下:
[root@localhost ~]# ./forls.sh
anaconda-ks.cfg
a.sql
a.txt
aw.txt
b.tx
b.txt
八、for循環遍歷參數
在f
o r循環中省去i n列表選項時,它將接受命令行位置參數作爲參數。實際上即指明:for params in"$@"
或者for params in"$*"
,下面的例子不使用i
n列表選項, for循環查看特定參數$@
或$*
,以從命令行中取得參數
#!/bin/sh
# forparam2
for params
do
echo "You supplied $params as a command line option"
done
下面的腳本包含in "$@"
,結果與上面的腳本相同:
#!/bin/sh
# forparam3
for params in "$@"
do
echo "You supplied $params as a command line option"
done
九、for循環實現查找文件
如果要查看一系列文件,可在for循環裏使用find命令,利用命令行參數,傳遞所有要查閱的文件.
#!/bin/sh
# forfind.sh
for loop
do
find / -name $loop -print
done
十、使用for循環備份文件
可以用for循環備份所有文件,只需將變量作爲cp命令的目標參數。這裏有一變量.bak,當在循環中使用cp命令時,它作爲此命令目標文件名。列表命令爲ls
#!/bin/sh
# forbak.sh
suffix=".bak"
for loop in `ls `
do
cp $loop $loop$suffix
done
十一、使用for批量刪除空文件
下面的例子中,
sed用於刪除所有空文件,並將輸出導至以.HOLD。 mv爲擴展名的新文件中,mv將這些文件移至初始文件中。
#!/bin/sh
# forsed.sh
for files in `ls LPSO*`
do
sed -e "/^$/d" $files >$files.HOLD
mv $files.HOLD $files
done
十二、for循環嵌入示例
下面腳本即爲嵌入for循環,這裏有兩個列表APPS和SCRIPTS。第一個包含服務器上應用的路徑,第二個爲運行在每個應用上的管理腳本。對列表APPS上的每一個應用,列表SCRIPTS裏的腳本將被運行,腳本實際上爲後臺運行。腳本使用tee命令在登錄文件上放一條目,因此輸出到屏幕的同時也輸出到一個文件。查看輸出結果就可以看出嵌入for循環怎樣使用列表SCRIPTS以執行列表APPS上的處理。
#!/bin/sh
# audit_run.sh
APPS="/apps/accts /apps/claims /apps/stock /apps/serv"
SCRIPTS="audit.check report.run cleanup"
LOGFILE=audit.log
MY_DATE=`date +%H:%M" on "%d/%m%Y`
# outer loop
for loop in $APPS
do
# inner loop
for loop2 in $SCRIPTS
do
echo "system $loop now running $loop2 at $MY_DATE" | tee -a\
$LOGFILE $loop $loop2 &
done
done
程序的運行結果如下:
tee: /apps/accts: No such file or directory
tee: /apps/accts: No such file or directory
system /apps/accts now running report.run at 20:18 on 21/112010
tee: /apps/accts: No such file or directory
system /apps/accts now running cleanup at 20:18 on 21/112010
tee: /apps/claims: No such file or directory
system /apps/claims now running audit.check at 20:18 on 21/112010
tee: /apps/claims: No such file or directory
system /apps/claims now running report.run at 20:18 on 21/112010
tee: /apps/claims: No such file or directory
system /apps/claims now running cleanup at 20:18 on 21/112010
tee: /apps/stock: No such file or directory
system /apps/stock now running audit.check at 20:18 on 21/112010
tee: /apps/stock: No such file or directory
system /apps/stock now running report.run at 20:18 on 21/112010
tee: /apps/stock: No such file or directory
system /apps/stock now running cleanup at 20:18 on 21/112010
tee: /apps/serv: No such file or directory
system /apps/serv now running audit.check at 20:18 on 21/112010
[root@localhost ~]# system /apps/accts now running audit.check at 20:18 on 21/112010
tee: /apps/serv: No such file or directory
system /apps/serv now running report.run at 20:18 on 21/112010
tee: /apps/serv: No such file or directory
system /apps/serv now running cleanup at 20:18 on 21/112010