1. 程式人生 > >Shell裡內建陣列BASH_REMATCH[n]個人解析

Shell裡內建陣列BASH_REMATCH[n]個人解析

先引用一段資料,出自:http://bbs.chinaunix.net/thread-4125147-1-1.html

紅色註釋為個人新增

--------------------------------------------------------------搬運內容分割線----------------------------------------------------------------

從 bash 3以上版本里,已經自帶正則匹配的功能, 很多情況下,可以不用awk/sed來做。 比如這個需求:

  1. <List>
  2.     <Job id="1" name="abc"/>
  3.     <Job id="2" name="zyz"/>
  4.     <Job id="3" name="beew"/>
  5. </List>
複製程式碼 想要得到這個結果。
  1. abc | 1
  2. zyz | 2
  3. beew | 3
複製程式碼 我們用純shell的方法。
  1. #!/bin/bash
  2. while read  line; do        //讀入變數line
  3.   if [[ $line =~ id=\"([0-9]+).*name=\"([^\"]*) ]]; then   //子模式1為([0-9]+);子模式2為([^\"]*)
  4.     echo "${BASH_REMATCH[2]} | ${BASH_REMATCH[1]}"  
  5.   fi
  6. done < file
複製程式碼 如果你對sed 裡的 \1 \2 的用法很熟的話,就應該很快的明白 BASH_REMATCH[1] 和 BASH_REMATCH[2] 代表了什麼。 

把樓下@rogantianwz的回覆帖在這裡,解釋的很不錯。
  1.     雙目運算子=~;它和==以及!=具有同樣的優先順序。如果使用了它,則其右邊的字串就被認為是一個擴充套件的正則表示式來匹配。如果字串和模式匹配,則返回值是0,否則返回1。如果這個正則表示式有語法錯誤,則整個條件表示式的返回值是2。如果打開了shell的nocasematch 選項則匹配時不考慮字母的大小寫。模式的任何部分都可以被引用以強制把其當作字串來匹配。由正則表示式中括號裡面的子模式匹配的字串被儲存在陣列變數BASH_REMATCH 中。BASH_REMATCH 中下標為0的元素是字串中與整個正則表示式匹配的部分。BASH_REMATCH 中下標為n的元素是字串中與第n 個括號裡面的子模式匹配的部分。

--------------------------------------------------------------搬運內容分割線----------------------------------------------------------------

我的理解:子模式1為匹配出現一次或多次(+號的作用)任意0~9字元;子模式2為出現零次或多次(*號的作用)的非雙引號"字元,其中[^\"]取一切非雙引號單個字元,反斜槓\用來轉義雙引號"。接下來的echo "${BASH_REMATCH[n]}"中,按照先讀取匹配子模式2的陣列內容BASH_REMATCH{2},即上例中的abc,xyz,beew等等,接著列印豎線|,最後讀取匹配子模式1的陣列內容,即1,2,3。

下面搬運一個匹配ip地址的指令碼

出處:http://www.yunweipai.com/archives/4660.html

--------------------------------------------------------------搬運內容分割線----------------------------------------------------------------

運維場景下,我們經常需要在伺服器上用正則表示式來匹配IP地址。

shell和其它程式語言一樣,也可以使用正則分組捕獲,不過不能使用 $1或\1這樣的形式來捕獲分組,可以通過陣列${BASH_REMATCH}來獲得,如${BASH_REMATCH[1]},${BASH_REMATCH[N]}

下面以ip="121.0.2.2"為例,shell指令碼程式碼如下(當然,你要做成更通用互動式的指令碼,可以通過expect來實現):

#!/bin/bash
ip="121.0.2.2"
if [[ $ip =~ ^([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$ ]]
then
    echo "Match"
    echo ${BASH_REMATCH[1]}
    echo ${BASH_REMATCH[2]}
    echo ${BASH_REMATCH[3]}
    echo ${BASH_REMATCH[4]}
else
    echo "Not match"
fi

--------------------------------------------------------------搬運內容分割線----------------------------------------------------------------

我的分析:

如果符合ip地址定義範圍,則返回結果為
Match
121
0
2
2
否則返回Not match(執行結果已實機驗證)

if判斷語句裡的正則表示式[0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5]意為匹配符合ip地址定義原則的欄位:當總位數為1~2時,符合要求的取值為0~99,當總位數為3的時候,符合的取值區間為100~199,200~249,250~255,其中豎線 | 的作用是或邏輯運算