1. 程式人生 > >[Linux]:Bash Shell的字串匹配方法

[Linux]:Bash Shell的字串匹配方法

 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#*/}