[Linux]:Bash Shell的字串匹配方法
阿新 • • 發佈:2019-01-01
Bash的字串匹配共有6種形式:
1. ${variable#pattern}
如果pattern匹配variable的開始部分,從variable的開始處刪除字元直到第一個匹配的位置,包括匹配部分,返回剩餘部分。
2. ${variable##pattern}
如果pattern匹配variable的開始部分,從variable的開始處刪除字元直到最後一個匹配的位置,包括匹配部分,返回剩餘部分。
3. ${variable%pattern}
如果pattern匹配variable的結尾部分,從variable的結尾處刪除字元直到第一個匹配的位置,包括匹配部分,返回剩餘部分。
4. ${variable%%pattern}
如果pattern匹配variable的結尾部分,從variable的結尾處刪除字元直到最後一個匹配的位置,包括匹配部分,返回剩餘部分。
5. ${variable/pattern/string}
6. ${variable//pattern/string}
最後這兩種用法用於匹配替換。因為我沒用到,先不說了。(busybox 1.0.1 不支援最後這兩種語法。)
舉例:
str=tftp://hostname.com/onepath/anotherpath
echo ${str#*/}
輸出:/hostname.com/onepath/anotherpath
echo ${str##*/}
輸出:anotherpath
echo ${str%/*}
輸出:tftp://hostname.com/onepath
echo ${str%%/*}
輸出:tftp:
--------------------
下面說一說具體怎麼用。
假設在某個系統中沒有sed和awk, 只有grep,tr和cut。
如果要取得網絡卡的mac地址,可以:
mac_addr=$(ifconfig eth0 | grep HWaddr | cut -d' ' -f11 | tr -d : )
echo $mac_addr
輸出:0150BF9886BF
後面再說為什麼我要把冒號去掉。這種方式在cut時要經過實驗才知道我們要的是第11個field。現在換另一種方式:
mac_addr=$(ifconfig eth0 | grep HWaddr | tr -d ' :')
echo $mac_addr
輸出:eth0LinkencapEthernetHWaddr0150BF9886BF
然後:
mac_addr=${mac_addr#*HWaddr}
echo $mac_addr
輸出:0150BF9886BF
現在要求寫一個程式,接受命令列給定一個網址去下載一個檔案,要求根據網址的協議的不同,採用不同的程式下載。如果給定的網址以.xml結尾,則認為要下載的檔案已經在給定的網址中指定,否則要下載的檔名為本機的mac地址加.xml副檔名,不包括mac中的冒號。
例如給定 tftp://host/file.xml,則要用tftp命令下載host上的file.xml檔案。
如果給定 http://host/path,則要用wget命令下載host/path上的0150BF9886BF.xml檔案。
先取網址的協議,採用從右向左最大匹配"://":
url=$1
proto=${url%%://*}
再判斷檔名是否已經給定, 採用從左向右最大匹配".xml":
[ -z "${url##*.xml}" ] || url=$url/$mac_addr.xml
如果 $proto = "http" 或者 "ftp"
則執行
wget $url -O local_file
如果 $proto = "tftp",這個有點麻煩,因為tftp的用法是:
tftp -g -r remote_file -l local_file host
所以還要把remote_file和host從url中提取出來。
先把url中的tftp://去掉:
tmp=${url#*://}
再從右向左最大匹配"/"得到host:
host=${tmp%%/*}
再從左向右最小匹配"/"得到路徑和檔名:
remote_file=${tmp#*/}
1. ${variable#pattern}
如果pattern匹配variable的開始部分,從variable的開始處刪除字元直到第一個匹配的位置,包括匹配部分,返回剩餘部分。
2. ${variable##pattern}
如果pattern匹配variable的開始部分,從variable的開始處刪除字元直到最後一個匹配的位置,包括匹配部分,返回剩餘部分。
3. ${variable%pattern}
如果pattern匹配variable的結尾部分,從variable的結尾處刪除字元直到第一個匹配的位置,包括匹配部分,返回剩餘部分。
4. ${variable%%pattern}
如果pattern匹配variable的結尾部分,從variable的結尾處刪除字元直到最後一個匹配的位置,包括匹配部分,返回剩餘部分。
5. ${variable/pattern/string}
6. ${variable//pattern/string}
最後這兩種用法用於匹配替換。因為我沒用到,先不說了。(busybox 1.0.1 不支援最後這兩種語法。)
舉例:
str=tftp://hostname.com/onepath/anotherpath
echo ${str#*/}
輸出:/hostname.com/onepath/anotherpath
echo ${str##*/}
輸出:anotherpath
echo ${str%/*}
輸出:tftp://hostname.com/onepath
echo ${str%%/*}
輸出:tftp:
--------------------
下面說一說具體怎麼用。
假設在某個系統中沒有sed和awk, 只有grep,tr和cut。
如果要取得網絡卡的mac地址,可以:
mac_addr=$(ifconfig eth0 | grep HWaddr | cut -d' ' -f11 | tr -d : )
echo $mac_addr
輸出:0150BF9886BF
後面再說為什麼我要把冒號去掉。這種方式在cut時要經過實驗才知道我們要的是第11個field。現在換另一種方式:
mac_addr=$(ifconfig eth0 | grep HWaddr | tr -d ' :')
echo $mac_addr
輸出:eth0LinkencapEthernetHWaddr0150BF9886BF
然後:
mac_addr=${mac_addr#*HWaddr}
echo $mac_addr
輸出:0150BF9886BF
現在要求寫一個程式,接受命令列給定一個網址去下載一個檔案,要求根據網址的協議的不同,採用不同的程式下載。如果給定的網址以.xml結尾,則認為要下載的檔案已經在給定的網址中指定,否則要下載的檔名為本機的mac地址加.xml副檔名,不包括mac中的冒號。
例如給定 tftp://host/file.xml,則要用tftp命令下載host上的file.xml檔案。
如果給定
先取網址的協議,採用從右向左最大匹配"://":
url=$1
proto=${url%%://*}
再判斷檔名是否已經給定, 採用從左向右最大匹配".xml":
[ -z "${url##*.xml}" ] || url=$url/$mac_addr.xml
如果 $proto = "http" 或者 "ftp"
則執行
wget $url -O local_file
如果 $proto = "tftp",這個有點麻煩,因為tftp的用法是:
tftp -g -r remote_file -l local_file host
所以還要把remote_file和host從url中提取出來。
先把url中的tftp://去掉:
tmp=${url#*://}
再從右向左最大匹配"/"得到host:
host=${tmp%%/*}
再從左向右最小匹配"/"得到路徑和檔名:
remote_file=${tmp#*/}