1. 程式人生 > 實用技巧 >Shell字串擷取

Shell字串擷取

Shell 擷取字串通常有兩種方式:從指定位置開始擷取和從指定字元(子字串)開始擷取。

格式說明
${string: start :length} 從 string 字串的左邊第 start 個字元開始,向右擷取 length 個字元。
${string: start} 從 string 字串的左邊第 start 個字元開始擷取,直到最後。
${string: 0-start :length} 從 string 字串的右邊第 start 個字元開始,向右擷取 length 個字元。
${string: 0-start} 從 string 字串的右邊第 start 個字元開始擷取,直到最後。
${string#*chars} 從 string 字串第一次出現 *chars 的位置開始,擷取*chars 右邊的所有字元。
${string##*chars} 從 string 字串最後一次出現 *chars 的位置開始,擷取*chars 右邊的所有字元。
${string%*chars} 從 string 字串第一次出現 *chars 的位置開始,擷取*chars 左邊的所有字元。
${string%%*chars} 從 string 字串最後一次出現 *chars 的位置開始,擷取*chars 左邊的所有字元。

從指定位置開始擷取

這種方式需要兩個引數:除了指定起始位置,還需要擷取長度,才能最終確定要擷取的字串。


既然需要指定起始位置,那麼就涉及到計數方向的問題,到底是從字串左邊開始計數,還是從字串右邊開始計數。答案是 Shell 同時支援兩種計數方式。

1) 從字串左邊開始計數

如果想從字串的左邊開始計數,那麼擷取字串的具體格式如下:

${string: start :length}

其中,string 是要擷取的字串,start 是起始位置(從左邊開始,從 0 開始計數),length 是要擷取的長度(省略的話表示直到字串的末尾)。

例如:

url="c.biancheng.net"
echo ${url: 2: 9}

結果為biancheng

再如:

url="c.biancheng.net
" echo ${url: 2} #省略 length,擷取到字串末尾

結果為biancheng.net

2) 從右邊開始計數

如果想從字串的右邊開始計數,那麼擷取字串的具體格式如下:

${string: 0-start :length}

同第 1) 種格式相比,第 2) 種格式僅僅多了0-,這是固定的寫法,專門用來表示從字串右邊開始計數。

這裡需要強調兩點:

  • 從左邊開始計數時,起始數字是 0(這符合程式設計師思維);從右邊開始計數時,起始數字是 1(這符合常人思維)。計數方向不同,起始數字也不同。
  • 不管從哪邊開始計數,擷取方向都是從左到右。


例如:

url="c.biancheng.net"
echo ${url: 0-13: 9}

結果為biancheng。從右邊數,b是第 13 個字元。


再如:

url="c.biancheng.net"
echo ${url: 0-13}  #省略 length,直接擷取到字串末尾

結果為biancheng.net

從指定字元(子字串)開始擷取

這種擷取方式無法指定字串長度,只能從指定字元(子字串)擷取到字串末尾。Shell 可以擷取指定字元(子字串)右邊的所有字元,也可以擷取左邊的所有字元。

1) 使用 # 號擷取右邊字元

使用#號可以擷取指定字元(或者子字串)右邊的所有字元,具體格式如下:

${string#*chars}

其中,string 表示要擷取的字元,chars 是指定的字元(或者子字串),*是萬用字元的一種,表示任意長度的字串。*chars連起來使用的意思是:忽略左邊的所有字元,直到遇見 chars(chars 不會被擷取)。

請看下面的例子:

url="http://c.biancheng.net/index.html"
echo ${url#*:}

結果為//c.biancheng.net/index.html


以下寫法也可以得到同樣的結果:

echo ${url#*p:}
echo ${url#*ttp:}

如果不需要忽略 chars 左邊的字元,那麼也可以不寫*,例如:

url="http://c.biancheng.net/index.html"
echo ${url#http://}

結果為c.biancheng.net/index.html


注意,以上寫法遇到第一個匹配的字元(子字串)就結束了。例如:

url="http://c.biancheng.net/index.html"
echo ${url#*/}

結果為/c.biancheng.net/index.html。url 字串中有三個/,輸出結果表明,Shell 遇到第一個/就匹配結束了。


如果希望直到最後一個指定字元(子字串)再匹配結束,那麼可以使用##,具體格式為:

${string##*chars}

請看下面的例子:

#!/bin/bash

url="http://c.biancheng.net/index.html"
echo ${url#*/}    #結果為 /c.biancheng.net/index.html
echo ${url##*/}   #結果為 index.html

str="---aa+++aa@@@"
echo ${str#*aa}   #結果為 +++aa@@@
echo ${str##*aa}  #結果為 @@@

2) 使用 % 擷取左邊字元

使用%號可以擷取指定字元(或者子字串)左邊的所有字元,具體格式如下:

${string%chars*}

請注意*的位置,因為要擷取 chars 左邊的字元,而忽略 chars 右邊的字元,所以*應該位於 chars 的右側。其他方面%#的用法相同,這裡不再贅述,僅舉例說明:

#!/bin/bash

url="http://c.biancheng.net/index.html"
echo ${url%/*}  #結果為 http://c.biancheng.net
echo ${url%%/*}  #結果為 http:

str="---aa+++aa@@@"
echo ${str%aa*}  #結果為 ---aa+++
echo ${str%%aa*}  #結果為 ---