SHELL複習摘要(二)
getopts命令
通過getopts可以更加容易的控制多個命令行參數。
一般格式:getopts option+string variable
while getopts ahfv OPTION
這裏while循環讀取命令行,option_string爲指定的5個選項(-a、-h、-f、-v),腳本中variable爲OPTION。注意這裏並沒用用連字符指定每個單個選項。getopts讀取option_string,獲知腳本中使用了有效選項。getopts接收完所有參數後,返回非零狀態,意即參數傳遞成功,變量OPTION保存最後處理參數。
getopts命令簡化了選項處理。它能理解POSIX選項中將多個選項字母組織到一起的用法,也可以用來遍歷整個命令行參數,一次一個參數。getopts的第一個參數使列出合法選項字母的一個字符串。如果選項字母后跟着冒號,則表示該選項需要一個參數,此參數是必須提供的。一旦遇到這樣的選項,getopts會放置參數值到變量OPTARG中。另一個變量OPTIND包含下一個要處理的參數的索引值。shell會把該變量初始化爲1。getopts的第二個參數爲變量名稱,在每次getopts調用時,該變量會被更新;它的值是找到的選項字母。當getopts找到不合法的選項時,它會將此變量設置爲一個問號字符。將冒號置於選項字符串中作爲第一個字符,可以使得getopts以兩種方式改變它的行爲:首先,它不會顯示任何錯誤信息;第二,除了將變量設置爲問號之外,OPTARG還包含給定的不合法選項字母。
例如:
#設置標誌變量爲空
file= verbose= quiet= long=
#開頭的冒號,是我們處理錯誤的方式
while getopts :f:vql opt
do
case $opt in
f) file=$OPTARG
;;
v) verbose=true
quiet=
;;
q) quiet=true
verbose=
;;
l) long=true
;;
‘?’) echo “$0: invalied option -$OPTARG”>&2
echo “Usage:$0 [-f file] [-vql] [files…]”>&2
exit 1
;;
esac
done
shift $((OPTIND - 1)) #刪除選項,留下參數
有時候有必要再腳本中指定命令行選項取值。getopts爲此提供了一種方式,即在option_string中將一個冒號放在選項後。例如:
getopts ahfvc: OPTION
上面一行腳本指出,選項a、h、f、v可以不加實際值進行傳遞,而選項c必須取值。使用選項取值時,必須使用變量OPTARG保存該值。如果試圖不傳值給該選項,會返回一個錯誤信息。將冒號放在option_string開始部分。如:
while getopts :ahfvc: OPTION
在case語句裏使用?創建一可用語句捕獲錯誤。
case
\?)echo “`basename $0` -[a h f v] –[c value] file”
;;
Esac
函數
函數(function)是指一段單獨的程序代碼,用以執行一些定義完整的單項工作。
function_name () {
command
return number
}
return語句會返回函數的退出值給調用它的腳本,在函數中使用exit會終止整個腳本。
read
-p會打印後面的readline內容。例如:read -p “Enter:” i
-r 會忽略讀取內容中的特殊字符如\。
額外的重定向運算符
set -C POSIX shell提供了防止文件被意外截斷的選項。執行set -C後,使用>重定向遇到目標文件已存在時,就會失敗。>|則會令set -C失效。
提供行內輸入(inline input)的<<與<<-:使用program<<delimiter,可以在shell腳本正文內提供輸入數據。這樣的數據叫作嵌入文件(here document)。默認情況下,shell可以在嵌入文件正文內做變量,命令和算術替換:如果定界符以任何一種形式引號括起來,shell則不會處理輸入的內文。
嵌入文件重定器的第二種形式有一個負號。這種情況下,所有開頭的製表符在傳遞給程序作輸入之前,都從嵌入文件與結束定界符中刪除。
以<>打開一個文件作爲輸入與輸出之用:使用program<>file,可供讀取和寫入操作。默認是在標準輸入上打開file。一般來說,<以只讀模式打開文件,而>以只寫模式打開文件。<>運算符則是以讀取與寫入兩種模式打開給定的文件。這交由program確定並充分利用;實際上,使用這個操作符並不需要太多的支持。
文件描述符處理
在系統內部,UNIX是以一個小的整數數字,稱爲文件描述符,表示每個進程的打開文件。傳統上shell允許你直接處理至多10個打開文件:從0~9。POSIX將大於9的文件描述符,保留給各實現自行定義。Ksh除外。
文件描述服0,1和2分別對應標準輸入,標準輸出和標準錯誤輸出。
exec命令可以用來改變shell本身I/O設置。
exec 2>/tmp/$0.log 重定向shell本身的標準錯誤輸出
exec 3</tmp/file 打開信文件描述符3
read name rank serno <&3 從該文件描述符3讀取
如果你希望取消標準錯誤輸出的重定向,可以先把它複製到一個新的文件以存儲文件描述符。例:
exec 5>&2 把原來的標準錯誤輸出保存到文件描述符5上
exec 2>/tmp/$0.log 重定向標準錯誤輸出
... 執行各種操作
exec 5>&2 將原始文件複製到文件描述符2
exec 5>&- 關閉文件描述府5,因爲不再需要了
exec爲單向操作。控制權不可能會回到腳本。
波浪號展開與通配符
shell有兩種與文件名相關的展開。第一個是波浪號展開,另一個稱之爲通配符展開或者全局展開或者路徑展開。
波浪號展開
如果命令行字符串的第一個字符爲波浪號或者便來那個指定的值裏任何未被引號括起來的冒號之後的第一個字符爲波浪號時,shell便會執行波浪號展開。好處:1.它是一種簡潔的概念表示方式,讓查閱shell腳本的人更清除腳本在做的事。2.它可以避免在程序裏把路徑名稱直接編碼。
例:
read user
vi /home/$user/.profile
read user
vi ~$user/.profile #是shell在系統的密碼數據庫裏,尋找用戶,在將~$user替換成$user。
如果有任何變動,用戶的子目錄位置變遷,那麼第一個代碼就需要重寫,但是第二個就避免了重寫的情況。
通配符展開
基本通配符
? 任何單一字符
*任何字符和字符串
[set] 任何在set裏的字符
[!set] 任何不在set裏的字符
例如:
[,.;] 逗號、句號或者分號
[-_] 破折號或者下劃線
命令替換
命令替換指shell執行命令並將命令替換部分替換爲執行該命令後的結果。命令替換有2個形式:
1. 使用反引號(也稱爲重音符號)。
echo outer `echo inner1 \`echo inner2\` inner1` outer
內嵌反引號時候需要用\轉義
2. 使用$(),推薦容易理解。
echo outer $(echo inner1 $(echo inner2) inner1) outer
內嵌雙引號無需轉義
引用
引用是用來防止shell將某些你想要的東西解釋成不同的意義。
反斜槓轉義:字符前置反斜槓
單引號:單引號強制shell將一對引號之間的所有字符都看成其字面上的意義。單引號被括在雙引號裏時候就無特殊意義了。
雙引號:雙引號就像單引號那樣,將括起來的文字視爲單一字符串。不過雙引號會確切的處理括起來的文字中的轉義字符和變量、算術、命令替換。
使用單引號的時機是你希望完全不處理的地方。否則,當你希望將多個單詞視爲單一字符串,但又需要shell爲你做些事情的時候,請使用雙引號。
shell命令執行順序
1. 按照固定的一組meta字符來將命令分割成token,有空格、製表符、換行符、分號、逗號、<、>、|、&。
2. 檢查第一個單詞是否是關鍵字。
3. 檢查第一個單詞是否是別名。
4. 檢查所有單詞是否需要波浪號展開。
5. 檢查是否有變量展開。
6. 檢查是否有命令替換。
7. 執行算術替換。
8. 檢查是否有$IFS字符。
9. 通配符展開。
eval語句
eval語句是在告訴shell取出eval的參數,並再執行它們一次,使它們經過整個命令行的處理步驟。
因爲變量展開在後,展開後|和more就變成ls的參數了。
使用eval後會把展開後的ls 、|和more重新送入shell,通過|分割爲2個命令,從而返回正確結果。
subShell與代碼塊
subShell是一羣被括在圓括號裏的命令,這些命令會在另外的進程中執行。
tar –cf - . | (cd ../;tar –xpf -)
代碼塊概念上與subShell雷同,只不過它不會建立新進程。代碼塊裏的命令以花括號括起來,且對主腳本的狀態會造成影響。
cd /some/directory || {echo could not change to /some/directory! >&2;exit 1}
subShell和代碼塊區別:
結構 定界符 認可的位置 另外的進程
subShell () 行上的任何位置 是
代碼塊 {} 在換行字符、分號或者關鍵字之後 否
腳本範例
AWK
awk裏一般常用到的內建標量變量
FILENAME 當前輸入文件的名稱
FNR 當前輸入文件的記錄數
FS 字段分隔字符(正則表達式)默認爲:” “
NF 當前記錄的字段數
NR 在工作中的記錄數
OFS 輸出字段分隔字符(默認爲:” “)
ORS 輸出記錄分隔字符(默認爲:”\n”)
RS 輸入記錄分隔字符(僅用於gawk與mawk裏的正則表達式)默認爲:”\n”
trap命令
trap命令用於指定在接收到信號後將要採取的行動。
trap命令的一種常見用途是在腳本程序被中斷時完成清理工作。歷史上,shell總是用數字來代表信號,而新的腳本程序應該使用信號的名字。你可以在命令提示符下輸入命令trap -l來查看信號編號及其關聯的名稱,在使用信號名時需要省略SIG前綴。
trap命令的參數分爲兩部分,前一部分是接收到指定信號時將要採取的行動,後一部分是要處理的信號名。
trap command signal
如果要重置某個信號的處理條件到其默認值,只需簡單的將command設置爲-。如果要忽略某個信號,就把command設置爲空字符串‘’。一個不帶參數的trap命令將列出當前設置的信號及其行動的清單。
注意:對於類似INT的信號,如果捕獲後,在trap設置的命令中不提供退出機制,程序將無法通過 Ctl+C 停止。
X/Open規範裏面規定的能夠被捕獲的比較重要的一些信號(括號裏面的數字是傳統的信號編號):
信 號 |
說 明 |
HUP(1) |
掛起,通常因終端掉線或用戶退出而引發 |
INT(2) |
中斷,通常因按下Ctrl+C組合鍵而引發 |
QUIT(3) |
退出,通常因按下Ctrl+\組合鍵而引發 |
ABRT(6) |
中止,通常因某些嚴重的執行錯誤而引發 |
ALRM(14) |
報警,通常用來處理超時 |
TERM(15) |
終止,通常在系統關機時發送 |
例如:
trap ‘exit 1’ HUP INT QUIT PIPE TERM
trap ‘rm –rf $tmpfile’EXIT
cmp
用途:
比較兩個文件的內容並報告不同的第一個字符。
補充說明:當相互比較的兩個文件完全一樣時,則該指令不會顯示任何信息。若發現有所差異,預設會標示出第一個不同之處的字符和列數編號。若不指定任何文件名稱或是所給予的文件名爲”-”,則cmp指令會從標準輸入設備讀取數據。
參數:
-c或–print-chars 除了標明差異處的十進制字碼之外,一併顯示該字符所對應字符。
-i<字符數目>或–ignore-initial=<字符數目> 指定一個數目。
-l或–verbose 標示出所有不一樣的地方。
-s或–quiet或–silent 不顯示錯誤信息。
-v或–version 顯示版本信息。
–help 在線幫助。
cmp –s a.txt b.txt