每一個章節中的腳本獨立成文。 python
代碼已測試過,Bash版本:GNU bash, version 3.00.15(1)-release (i686-asianux-linux-gnu) linux
使用環境變量的Shell腳本,有一個隱藏的危險:它們可能部分正確的指向不存在的程序。好比你決定使用環境變量PAGER來靈活的演示腳本輸出,而不是經過編寫一個特殊的工具,那麼如何肯定PAGER這個值已經設置正確了呢?畢竟它不是一個有效的程序,你的腳本可能會崩潰。 正則表達式
下面的這個腳本代表了在系統路徑中,如何經過測試來肯定一個給定的程序可否查找獲得。同時,它也很好的演示了一系列不一樣的腳本技術,包括腳本函數和變量切片(slicing)。 shell
第一個腳本
inpath.sh ---- 在系統路徑PATH中尋找程序 bash
inpath.sh #!/bin/sh in_path() { # 給定一個命令和路徑,嘗試找到命令。 # 若是找到了,而且可執行,返回0,不然返回1. # 注意,它暫時性的修改了IFS(輸入域分隔符),但完成後會重置。 cmd=$1 path=$2 retval=1 oldIFS=$IFS IFS=":" # 設置域分隔符 for directory in $path do if [ -x $directory/$cmd ]; then retval=0 # 執行到這步,代表在PATH中找到了程序 fi done IFS=$oldIFS # 還原域分隔符 return $retval } checkForCmdInPath() { var=$1 # 提示用法: # ${var#expr},從var開頭刪除最短匹配expr的字符串 # ${var%expr},從var結尾位置刪除最短匹配expr的字符串 # 在Bash中,使用${var:0:1}和cut -c1也能夠。 if [ "$var" != "" ]; then if [ "${var%${var#?}}" = "/" ]; then if [ ! -x $var ]; then return 1 fi elif ! in_path $var $PATH; then return 2 fi fi }測試inpath.sh:向驗證程序傳遞一個初始參數,而後驗證返回碼。下面的代碼直接添加在inpath.sh中。
inpath.sh if [ $# -ne 1 ]; then echo "Usage: $0 commmand" >&2 exit 1 fi checkForCmdInPath "$1" case $? in # $?是上個命令或是腳本的退出碼 0)echo "$1 found in PATH";; 1)echo "$1 not found or not executable";; 2)echo "$1 not found in PATH";; esac exit 0
測試的3種狀況:
1.程序存在: 函數
inpath.sh python
輸出:python found in PATH 工具
2.程序存在,但不在PATH上: 測試
inpath.sh test.sh
輸出:test.sh not found in PATH spa
3.程序不存在,但該程序有一個完整的包含路徑的名字: code
inpath.sh /usr/bin/python4
輸出:/usr/bin/python4 not found or not executable
其中,python你們都知道的,test.sh是一個可執行文件,python4估計這幾年都不會有的,哈哈。
分析下上面的腳本
上面代碼中最不經常使用的地方可能就是:
${var%${var#?}}
它是POSIX的變量切片方法。它有2個嵌套,內部嵌套 ${var#?},取得除變量var第一個字母外的剩餘內容,其中?是一個正則表達式,表示通配一個字符。外層 ${var%pattern},生成一個除去右匹配pattern後的剩餘子串。在此例中,剩下的就是字符串的第一個字母。
check-ForCmdInPath能夠區分是一個程序仍是一個包含有路徑的文件名。方法是判斷第一個字母是否是斜線「/」。
若是上面的切片方法使用起來有難度的話,能夠使用另外一種Bash和Ksh支持的方法,子串函數
${varname:start:size}
好比,${varname:1:1}就是產生一個只有第一個字母的子串。注意,Shell中的這種用法,字符串下標是從1開始的。固然了,若是這2種技術你都不愛用的話,可是又想只取第一個字母,能夠用cut命令:
$(echo $var | cut -c1)