1. 程式人生 > >grep零寬斷言&正則表達式

grep零寬斷言&正則表達式

grep零寬斷言 正則表達式

一、grep零寬斷言:
(匹配寬度為零,滿足一定的條件/斷言)
零寬斷言用於查找在某些內容(但並不包括這些內容)之前或之後的東西,也就是說它們像 \b ^ $ \< \> 這樣的錨定作用,用於指定一個位置,這個位置應該滿足一定的條件(即斷言),因此它們也被稱為零寬斷言。 斷言用來聲明一個應該為真的事實。正則表達式中只有當斷言為真時才會繼續進行匹配。
分為四種:
1)先行斷言 (?=exp)//表示匹配表達式前面的位置
例如 [a-z]*(?=ing) 可以匹配 cooking 和 singing 中的 cook 與 sing
註意:先行斷言的執行步驟是這樣的先從要匹配的字符串中的最右端找到第一個 ing (也就是先行斷言中的表達式)然後 再匹配其前面的表達式,若無法匹配則繼續查找第二個 ing 再匹配第二個 ing 前面的字符串,若能匹配則匹配,符合正則的貪婪性。
例如: .*(?=ing) 可以匹配 "cooking singing" 中的 "cooking sing" 而不是 cook

2)後發斷言 (?<=exp) //表示匹配表達式後面的位置
例如(?<=abc).* 可以匹配 abcdefg 中的 defg

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) 這種類型的分組不對正則表達式的處理產生任何影響,用於提供註釋讓人閱讀

aaa bbb CD="123" fd //取出CD的值
grep -oP '(?<=CD=")\d+' file
以 CD=" 為後發斷言,匹配它後面的多個數字。

實例:

create_db_msg: {"rdsj817z94agw6656d42":["drds_mt_revu_0008","drds_mt_revu_0009","drds_mt_revu_0010","drds_mt_revu_0011","drds_mt_revu_0012","drds_mt_revu_0013","drds_mt_revu_0014","drds_mt_revu_0015"],"rdsb4sk15ab96g03gezp":["drds_mt_revu_0000","drds_mt_revu_0001","drds_mt_revu_0002","drds_mt_revu_0003","drds_mt_revu_0004","drds_mt_revu_0005","drds_mt_revu_0006","drds_mt_revu_0007"],"rdsv3q667r37agb27k8a":["drds_mt_revu_0016","drds_mt_revu_0017","drds_mt_revu_0018","drds_mt_revu_0019","drds_mt_revu_0020","drds_mt_revu_0021","drds_mt_revu_0022","drds_mt_revu_0023"]}
[root@wolf test]# cat file  |grep -oP '(?<=")rds.*?(?=":)'  | sort | uniq 
rdsb4sk15ab96g03gezp
rdsj817z94agw6656d42
rdsv3q667r37agb27k8a


註意:這裏的 rds.*?中的?有特殊意義,默認rds.*會貪婪匹配到最後一個

二、正則表達式的30min
\btom\b //“\b"中間tom代表是一個單詞
\d 表示一個數字
\d{2}-\d{8}。 這裏\d後面的{2}({8})的意思是前面\d必須連續重復匹配2次(8次)。
\s匹配任意的空白符,包括空格,制表符(Tab),換行符,中文全角空格等。
\w匹配字母或數字或下劃線或漢字等。
. 匹配除換行符以外的任意字符
\d 匹配數字
\b 匹配單詞的開始或結束
^ 匹配字符串的開始 //^和$匹配的是行
$ 匹配字符串的結束

^\d{5,12}$ //填寫的QQ號必須為5位到12位數字

備註:"\d"等這些字符只有在perl{正則支持的相對完整} 中能夠使用

轉義):
\字符
重復):
* 重復零次或更多次
+ 重復一次或更多次
? 重復零次或一次
{n} 重復n次
{n,} 重復n次或更多次
{n,m} 重復n到m次

[root@wolf test]# ifconfig   |grep -oP "\b(\d{1,}\.)(\d{1,3}\.)(\d{1,3}\.)\d{1,3}\b"  //取出ip地址
10.25.57.183
255.255.252.0
10.25.59.255
255.255.252.0
127.0.0.1
255.0.0.0

字符類)
[.?!]匹配標點符號(.或?或!)。
[0-9]代表的含意與\d就是完全一致的
[a-z0-9A-Z_]也完全等同於\w
\(?0\d{2}[) -]?\d{8} //匹配(010)88886666,或022-22334455,或02912345678等
( 出現0或者1次,接著是數字0,字符出現2次

[root@localhost test]# cat file
(010)88886666
022-22334455
02912345678
[root@localhost test]# cat file  |egrep "\(?[[:digit:]]{3}\)?\-?[[:digit:]]{8}"
[root@localhost test]# cat file  |grep "(\?[[:digit:]]\{3\})\?\-\?[[:digit:]]\{8\}"
[root@localhost test]# cat file  |egrep "\(?0[[:digit:]]{2}[)-]?[[:digit:]]{8}"
grep中"("和egrep中的"\("一樣,
grep中的"\?"和egrep中的"?"一樣

分枝條件):
0\d{2}-\d{8}|0\d{3}-\d{7}這個表達式能匹配兩種以連字號分隔的電話號碼:一種是三位區號,8位本地號(如010-12345678),一種是4位區號,7位本地號(0376-2233445)。
分組):
[root@localhost test]# ifconfig | egrep -o "([[:digit:]]{1,3}\.){3}[[:digit:]]"
192.168.3.1
192.168.3.2
255.255.255.0
127.0.0.1
255.0.0.0

((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?) //匹配ip地址
[root@localhost test]# ifconfig |egrep -o "(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?\.){3}(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)"

反義):
\W 匹配任意不是字母,數字,下劃線,漢字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非數字的字符
\B 匹配不是單詞開頭或結束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou這幾個字母以外的任意字符

例子:\S+匹配不包含空白符的字符串。
<a[^>]+>匹配用尖括號括起來的以a開頭的字符串。

後向應用):
後向引用用於重復搜索前面某個分組匹配的文本。例如,\1代表分組1匹配的文本。
\b(\w+)\b\s+\1\b可以用來匹配重復的單詞,像go go, 或者kitty kitty。

常用分組語法): //分類 代碼/語法 說明
==============================================================
捕獲
(exp) 匹配exp,並捕獲文本到自動命名的組裏
(?<name>exp) 匹配exp,並捕獲文本到名稱為name的組裏,也可以寫成(?'name'exp)
(?:exp) 匹配exp,不捕獲匹配的文本,也不給此分組分配組號
零寬斷言
(?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp後面的位置
(?!exp) 匹配後面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置
註釋 (?#comment) 這種類型的分組不對正則表達式的處理產生任何影響,用於提供註釋讓人閱讀
第三個(?:exp)不會改變正則表達式的處理方式,只是這樣的組匹配的內容不會像前兩種那樣被捕獲到某個組裏面,也不會擁有組號。

貪婪與懶惰):
當正則表達式中包含能接受重復的限定符時,通常的行為是(在使整個表達式能得到匹配的前提下)匹配盡可能多的字符。以這個表達式為例:a.*b,它將會匹配最長的以a開始,以b結束的字符串。如果用它來搜索aabab的話,它會匹配整個字符串aabab。這被稱為貪婪匹配。
加入需要懶惰匹配,也就是匹配盡可能少的字符。前面給出的限定符都可以被轉化為懶惰匹配模式,只要在它後面加上一個問號?。這樣.*?就意味著匹配任意數量的重復
但是在能使整個匹配成功的前提下使用最少的重復。現在看看懶惰版的例子吧:
[root@localhost test]# echo "aababaab" |grep -oP "a.*b"
aababaab
[root@localhost test]# echo "aababaab" |grep -oP "a.*?b"
aab
ab
aab

懶惰限定符://尚未理解到位
代碼/語法 說明
*? 重復任意次,但盡可能少重復
+? 重復1次或更多次,但盡可能少重復
?? 重復0次或1次,但盡可能少重復
{n,m}? 重復n到m次,但盡可能少重復
{n,}? 重復n次以上,但盡可能少重復

#echo "123,123,123,123" |grep -oP "(\d{1,3})?"
123

#echo "123,456,123,789" |grep -oP "(\d{1,3}\,){1,}?"
123,
456,
123,

[[email protected] /root] //{n,}?用法
#echo "123,456,123,789" |grep -oP "(\d{1,3}\,){1,}"
123,456,123,

[[email protected] /root] //零寬對比
#echo "123,456,123,789" |grep -oP "(?<=^).*(?=,)"
123,456,123

[[email protected] /root]
#echo "123,456,123,789" |grep -oP "(?<=^).*?(?=,)"
123

三、正則表達式手冊
表達式全集:



字符描述
\將下一個字符標記為一個特殊字符、或一個原義字符、或一個向後引用、或一個八進制轉義符。例如,“n”匹配字符“n”。“\n”匹配一個換行符。串行“\\”匹配“\”而“\(”則匹配“(”。
^匹配輸入字符串的開始位置。如果設置了RegExp對象的Multiline屬性,^也匹配“\n”或“\r”之後的位置。
$匹配輸入字符串的結束位置。如果設置了RegExp對象的Multiline屬性,$也匹配“\n”或“\r”之前的位置。
*匹配前面的子表達式零次或多次。例如,zo*能匹配“z”以及“zoo”。*等價於{0,}。
+匹配前面的子表達式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等價於{1,}。
?匹配前面的子表達式零次或一次。例如,“do(es)?”可以匹配“does”或“does”中的“do”。?等價於{0,1}。
{n}n是一個非負整數。匹配確定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的兩個o。
{n,}n是一個非負整數。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等價於“o+”。“o{0,}”則等價於“o*”。
{n,m}mn均為非負整數,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”將匹配“fooooood”中的前三個o。“o{0,1}”等價於“o?”。請註意在逗號和兩個數之間不能有空格。
?當該字符緊跟在任何一個其他限制符(*,+,?,{n},{n,},{n,m})後面時,匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字符串,而默認的貪婪模式則盡可能多的匹配所搜索的字符串。例如,對於字符串“oooo”,“o+?”將匹配單個“o”,而“o+”將匹配所有“o”。
.匹配除“\n”之外的任何單個字符。要匹配包括“\n”在內的任何字符,請使用像“(.|\n)”的模式。
(pattern)匹配pattern並獲取這一匹配。所獲取的匹配可以從產生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中則使用$0…$9屬性。要匹配圓括號字符,請使用“\(”或“\)”。
(?:pattern)匹配pattern但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行存儲供以後使用。這在使用或字符“(|)”來組合一個模式的各個部分是很有用。例如“industr(?:y|ies)”就是一個比“industry|industries”更簡略的表達式。
(?=pattern)正向肯定預查,在任何匹配pattern的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。預查不消耗字符,也就是說,在一個匹配發生後,在最後一次匹配之後立即開始下一次匹配的搜索,而不是從包含預查的字符之後開始。
(?!pattern)正向否定預查,在任何不匹配pattern的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。預查不消耗字符,也就是說,在一個匹配發生後,在最後一次匹配之後立即開始下一次匹配的搜索,而不是從包含預查的字符之後開始
(?<=pattern)反向肯定預查,與正向肯定預查類擬,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
(?<!pattern)反向否定預查,與正向否定預查類擬,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。
x|y匹配x或y。例如,“z|food”能匹配“z”或“food”。“(z|f)ood”則匹配“zood”或“food”。
[xyz]字符集合。匹配所包含的任意一個字符。例如,“[abc]”可以匹配“plain”中的“a”。
[^xyz]負值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“p”。
[a-z]字符範圍。匹配指定範圍內的任意字符。例如,“[a-z]”可以匹配“a”到“z”範圍內的任意小寫字母字符。
[^a-z]負值字符範圍。匹配任何不在指定範圍內的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”範圍內的任意字符。
\b匹配一個單詞邊界,也就是指單詞和空格間的位置。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。
\B匹配非單詞邊界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\cx匹配由x指明的控制字符。例如,\cM匹配一個Control-M或回車符。x的值必須為A-Z或a-z之一。否則,將c視為一個原義的“c”字符。
\d匹配一個數字字符。等價於[0-9]。
\D匹配一個非數字字符。等價於[^0-9]。
\f匹配一個換頁符。等價於\x0c和\cL。
\n匹配一個換行符。等價於\x0a和\cJ。
\r匹配一個回車符。等價於\x0d和\cM。
\s匹配任何空白字符,包括空格、制表符、換頁符等等。等價於[ \f\n\r\t\v]。
\S匹配任何非空白字符。等價於[^ \f\n\r\t\v]。
\t匹配一個制表符。等價於\x09和\cI。
\v匹配一個垂直制表符。等價於\x0b和\cK。
\w匹配包括下劃線的任何單詞字符。等價於“[A-Za-z0-9_]”。
\W匹配任何非單詞字符。等價於“[^A-Za-z0-9_]”。
\xn匹配n,其中n為十六進制轉義值。十六進制轉義值必須為確定的兩個數字長。例如,“\x41”匹配“A”。“\x041”則等價於“\x04&1”。正則表達式中可以使用ASCII編碼。.
\num匹配num,其中num是一個正整數。對所獲取的匹配的引用。例如,“(.)\1”匹配兩個連續的相同字符。
\n標識一個八進制轉義值或一個向後引用。如果\n之前至少n個獲取的子表達式,則n為向後引用。否則,如果n為八進制數字(0-7),則n為一個八進制轉義值。
\nm標識一個八進制轉義值或一個向後引用。如果\nm之前至少有nm個獲得子表達式,則nm為向後引用。如果\nm之前至少有n個獲取,則n為一個後跟文字m的向後引用。如果前面的條件都不滿足,若nm均為八進制數字(0-7),則\nm將匹配八進制轉義值nm
\nml如果n為八進制數字(0-3),且m和l均為八進制數字(0-7),則匹配八進制轉義值nml。
\un匹配n,其中n是一個用四個十六進制數字表示的Unicode字符。例如,\u00A9匹配版權符號(?)。

常用匹配:

用戶名/^[a-z0-9_-]{3,16}$/
密碼/^[a-z0-9_-]{6,18}$/
十六進制值/^#?([a-f0-9]{6}|[a-f0-9]{3})$/
電子郵箱/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/
/^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/
URL/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/
IP 地址/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)/
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
HTML 標簽/^<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)$/
刪除代碼\\註釋(?<!http:|\S)//.*$
Unicode編碼中的漢字範圍/^[\u2E80-\u9FFF]+$/


參考博客:
http://tool.oschina.net/uploads/apidocs/jquery/regexp.html
https://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html




grep零寬斷言&正則表達式