零寬斷言的意思是(匹配寬度爲零,滿足一定的條件/斷言) 我也不知道這個詞語是那個王八蛋發明的,簡直是太拗口了。
零寬斷言用於查找在某些內容(但並不包括這些內容)之前或之後的東西,也就是說它們像 \b ^ $ \< \> 這樣的錨定作用,用於指定一個位置,這個位置應該滿足一定的條件(即斷言),因此它們也被稱爲零寬斷言。 斷言用來聲明一個應該爲真的事實。正則表達式中只有當斷言爲真時纔會繼續進行匹配。
其中零寬斷言又分四種:
1)
先行斷言 也叫零寬度正預測先行斷言(?=exp) -- 表示匹配表達式前面的位置
例如 [a-z]*(?=ing) 可以匹配 cooking 和 singing 中的 cook 與 sing 。
注意:先行斷言的執行步驟是這樣的先從要匹配的字符串中的最右端找到第一個 ing (也就是先行斷言中的表達式)然後 再匹配其前面的表達式,若無法匹配則繼續查找第二個 ing 再匹配第二個 ing 前面的字符串,若能匹配則匹配,符合正則的貪婪性。
例如: .*(?=ing) 可以匹配 "cooking singing" 中的 "cooking sing" 而不是 cook
2)
後發斷言 也叫零寬度正回顧後發斷言(?<=exp) -- 表示匹配表達式後面的位置
例如(?<=abc).* 可以匹配 abcdefg 中的 defg
注意:後發斷言跟先行斷言恰恰相反 它的執行步驟是這樣的:先從要匹配的字符串中的最左端找到第一個abc(也就是先行斷言中的表達式)然後 再匹配其後面的表達式,若無法匹配則繼續查找第二個 abc 再匹配第二個 abc 後面的字符串,若能匹配則匹配。
例如(?<=abc).* 可以匹配 abcdefgabc 中的 defgabc 而不是 abcdefg
3)
負向零寬斷言
負向零寬斷言 (?!exp) 也是匹配一個零寬度的位置,不過這個位置的“斷言”取表達式的反值,例如 (?!exp) 表示 "exp" 前面的位置,如果 "exp" 不成立 ,匹配這個位置;如果 "exp" 成立,則不匹配。同樣,負向零寬斷言也有“先行”和“後發”兩種,負向零寬後發斷言爲 (?<!exp)
負向零寬後發斷言(?<!exp)
負向零寬先行斷言 (?!exp)
負向零寬斷言要注意的跟正向的一樣。
常用分組語法
分類 代碼/語法 說明
捕獲 (exp) 匹配exp,並捕獲文本到自動命名的組裏
(?<name>exp) 匹配exp,並捕獲文本到名稱爲name的組裏,也可以寫成(?'name'exp)
(?:exp) 匹配exp,不捕獲匹配的文本,也不給此分組分配組號
零寬斷言 (?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp後面的位置
(?!exp) 匹配後面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置
註釋 (?#comment) 這種類型的分組不對正則表達式的處理產生任何影響,用於提供註釋讓人閱讀
例子:
cat file
aaa bbb CD="123" fd
要取出CD後面的值:
grep -oP '(?<=CD=")\d+' file
[解析]
以 CD=" 爲後發斷言,匹配它後面的多個數字。
cat file
Rx Optical Power: -5.01dBm, Tx Optical Power: -2.41dBm
要取出那幾個分貝的值:
-5.01
-2.41
grep -oP '(?<=: ).*?(?=d)' file
[解析]
後發斷言 ”: “ 後面的字符串,直到 d 字符前面的字符串,? 號的作用是避免貪婪匹配。
cat file
["check_ssh",ok],["check_eth",ok],["check_disk",ok],["check_swap",ok],["check_mem",ok],["check_hardware",false],["check_filesystem",false],["check_port",ok],["check_redis-server",ok],["check_login",ok]
取出[ ]中含 false 字樣的內容:
check_hardware
check_filesystem
grep -Po '[^"]+(?=",false)' file
總結:
斷言的匹配方式有兩種,一種是從最左邊開始查找字符串,另外一種是從最右邊開始查找字符串
1、cat file
aaa bbb CD="123" fd
要取出CD後面的值:
grep -oP '(?<=CD=")\d+' file
在此例子中,如果想要取出CD後面的數字字符的話,首先從左邊開吃查找CD=”這個字符串,查找到之後取出後面跟的數字字符\d+。其中<=表示匹配字符串從字符串的最左邊開始。
2、cat file
Rx Optical Power: -5.01dBm, Tx Optical Power: -2.41dBm
要取出那幾個分貝的值:
-5.01
-2.41
grep -oP '(?<=: ).*?(?=d)' file
從左邊開始向右邊尋找,查找到: (冒號加上空格),這個字符串所在的爲止,.*?意思是去掉grep的貪婪匹配,?=d意思是結束符號是d。去掉貪婪模式是什麼意思呢,也就是如果匹配到d只有就結束第一次的匹配。
grep -oP '(?<=: ).*(?=d)' file
-5.01dBm, Tx Optical Power: -2.41
如果不加?,那麼就會匹配到對後面的那個符號d。
3、
cat file
["check_ssh",ok],["check_eth",ok],["check_disk",ok],["check_swap",ok],["check_mem",ok],["check_hardware",false],["check_filesystem",false],["check_port",ok],["check_redis-server",ok],["check_login",ok]
取出[ ]中含 false 字樣的內容:
check_hardware
check_filesystem
grep -oP '[^"]+(?=",false)' d
從右邊開始查找false關鍵字,查找到之後,找到左邊的不是以符號”開始的字符,這樣就匹配到了false左邊中括號內的字符串。
Perl常用轉義字符:
\b 單詞的邊界
\w 表示[a-zA-Z0-9_]字母數字下劃線
\W 表示不在[a-zA-Z0-9_]字母數字下劃線中的字符
\d [0-9]中的一個數字
\D 不在[0-9]中的任意字符