String Substitution
在宣告變數時,有可能會因為疏忽而打錯;或是在寫給使用者使用的 script,每次都要詳細指定參數的麻煩....
其實這些錯誤或麻煩都可以避免,只要稍微修改一下變數的使用方式(搭配符號「{ }」)即可,以下用一張圖表來說明:
Operator | 作用 | 目的 | 範例 |
${varname:-word} | 假如 varname 變數存在,並且不是 null,則回傳變數內容;反之則回傳 word | 用於設定變數預設值 | ${count:-0} 若變數 count 未定義,則回傳 0 |
${varname:=word} | 假如 varname 變數存在,並且不是 null,則回傳變數內容;反之則設定此變數的值為 word,再回傳變數的值 | 用於將未定義的變數設定預設值 | ${count:=0} 若變數 count 未定義,則設定 count 變數的值為 0 並回傳 |
${varname:?message} | 假如 varname 變數存在,並且不是 null,則回傳變數內容;反之則顯示「varname: message」,並中斷目前的命令或 script。 | 用來針對未定義的變數進行 debug | ${count:?"undefined!"} 若變數 count 未定義,則會顯示「count: undefined!」,並中斷程式執行 |
${varname:+word} | 假如 varname 變數存在,並且不是 null,則回傳 word | 用來測試變數是否存在 | ${count:+1} 若變數 count 存在,則回傳 1 |
${varname:offset:length} | 回傳 varname 變數的值中,從第 offset 的字元開始(變數值的第一個位置為 0),長度為 length 的字串。 有以下幾種用法:
| 取得變數所儲存字串的部分字串 | count="frogfootman" ${count:4} => footman ${count:4:4} => foot |
像是表格中的第一種用法,就相當適用於必須為變數指定預設值的情形下。
以下直接用個例子來說明使用方式,假設我們檔案「sort-data.txt」,內容如下:
8 eight接著要寫一支 script 來根據最前面的數字作排序,並顯示指定的行數:
9 nine
1 one
2 two
3 three
7 seven
5 five
6 six
4 four
0 zero
執行結果如下:#!/bin/bash
# 檔案名稱:highest.sh
# 檢查 file 名稱是否有輸入
fileName=${1:?"filename missing, please check your file."}
# 設定預設顯示的行數
# 若使用者未輸入第二個參數就預設為 5
displayLine=${2:-5}
# sort 是用來排序的程式
# 參數「n」指定以數字為依據作排序
# 參數「r」則是 reverse 的意思,由大排到小
# head 是用來取「前幾行」
sort -nr $fileName | head -$displayLine
# 沒指定檔名時
shell> sh highest.sh
highest.sh: line 5: 1: filename missing, please check your file.
# 未指定所要顯示的行數
shell> sh highest.sh sort-data.txt
9 nine
8 eight
7 seven
6 six
5 five
# 指定顯示行數
shell> sh highest.sh sort-data.txt 3
9 nine
8 eight
7 seven
Patterns & Pattern Matching
說到字串處理,怎麼可以缺乏正規表示式呢?
當然 bash 中提供的不是正規表示式,不過提供的也是類似的功能,以下用一個表格來介紹:
Operator | 作用 |
${variable#pattern} | 從字串開頭開始比對,當 pattern 符合變數中的值,即不需繼續比對,僅比對至最短的符合字串,刪除比對到的部分並回傳剩下的變數值 |
${variable##pattern} | 同上,會回傳刪除比對後的變數值,但所採取的是貪婪比對,會一直比對到最長的部分為止 |
${variable%pattern} | 從字串尾端開始比對,當 pattern 符合變數中的值,即不需繼續比對,僅比對至最短的符合字串,刪除比對到的部分並回傳剩下的變數值 |
${variable%%pattern} | 同上,會回傳刪除比對後的變數值,但所採取的是貪婪比對,會一直比對到最長的部分為止 |
${variable/pattern/string} | 差異處: 在 variable 與 pattern 比對後,在上面的 operator 中,只有第一個比對到的字串會被更換為 string;在下面的 operator 中則會取代所有比對到的字串。 相同處:
|
${variable//pattern/string} |
以下直接用範例來說明:
繼續提到上面說的 pattern,有更進階的用法,可以進行多重比對,只要把每個 pattern 以符號「|」相隔即可,以下用表格來說明:myPath="/home/cam/book/long.file.name"
# 將兩個「/」之間的內容都刪除(貪婪比對)
echo ${myPath##/*/} # long.file.name
# 效果同上(因為 * 也可以代表 /)
echo ${myPath##*/} # long.file.name
# 將兩個「/」之間的內容刪除
echo ${myPath#/*/} # cam/book/long.file.name
# 從尾端開始比對,將比對符合結果刪除
echo ${myPath%.*} # /home/cam/book/long.file
# 從尾端開始比對,將比對符合結果刪除(貪婪比對)
echo ${myPath%%.*} # /home/cam/book/long
myPhotoName="myphoto.png"
# 將副檔名 png 改為 jpg
echo ${myPhotoName%.png}.jpg # myphoto.jpg
myEnvPath="/home/user/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin"
# 將「:」全部換成斷行字元,結果如下:
# /home/user/bin
# /usr/local/bin
# /bin
# /usr/bin
# /usr/X11R6/bin
echo -e ${myEnvPath//:/'\n'}
Operator | 說明 | 範例 | 效果 |
*(PatternList) | 符合 0 個到多個指定的 pattern 清單 | *(alice|hatter|hare) | 字串中出現 alice 或是 hatter 或是 hare,甚至完全沒有,都符合 |
+(PatternList) | 符合 1 個到多個指定的 pattern 清單 | +(alice|hatter|hare) | 字串中出現 alice 或是 hatter 或是 hare 都符合 |
+[0-9] | 僅數字符合 | ||
?(PatternList) | 符合 0 個到 1 個指定的 pattern 清單 | ?(alice|hatter|hare) | 字串中僅出現一次 alice 或是 hatter 或是 hare,或是完全沒有,就符合 |
@(PatternList) | 剛好完全符合指定 pattern 清單的其中 1 個 | @(alice|hatter|hare) | 僅有 alice、hatter、hare 這三個字串符合(精確比對) |
!(PatternList) | 完全不符合指定的 pattern 清單 | !(alice|hatter|hare) | 只要字串中沒有 alice、hatter、hare 即符合 |
!(vt+([0-9])) | 只要字串中沒有「vt+數字」的部分即符合 |
至於如何使用,就要靠使用者的創意與巧思了!
Length Operator
最後,要來介紹如何取得變數值的長度,這很簡單,語法如下:
${#varname}以下來個簡單的範例:
myFile="myfile.txt"
echo ${#myFile} # 輸出 10
沒有留言:
張貼留言