基礎(chǔ)正則
.
:匹配任意單個字符,但不能匹配換行符\n
*
:匹配前面那個字符0或多次?
:匹配前面那個字符0或一次+
:匹配前面那個字符1次以上{M,N}
:匹配前面那個字符至少M,最多N次{M,}
:匹配前面那個字符至少M次,最多無限制{,N}
:匹配前面那個字符最多N次(最少當然是0次)。注意,perl正則不支持這種方式{M}
:匹配前面那個字符正好M次^
:匹配行首位置,注意匹配的是位置,不是字符$
:匹配行尾位置,注意匹配的是位置,不是字符特殊且常用的的組合正則表達式:
^$
:它表示匹配空行.*
:匹配任意長度的任意字符,但不能匹配換行符。真正的匹配任意長度的任意字符,見下面需要解釋清楚的是這些量詞(也就是上面匹配的次數(shù)元字符)的特殊性:當使用了匹配多次的量詞時(如匹配3-5次的{3,5}
),且量詞前面的字符有多種可能性(如中括號序列[abc]
),那么量詞的次數(shù)可以作用于任一字符。有些不好理解,但看示例就知道了:
[abc]{3,5} # 表示abc任意字符都可以出現(xiàn),比如全是a,或者ab同時出現(xiàn),但總的出現(xiàn)次數(shù)為3-5次.* # 表示任一字符(除換行符),可以任意出現(xiàn)任意次數(shù),它不表示a之后就必須全是a.+ # 表示任一字符(除換行符),可以任意出現(xiàn)至少一次,它不表示a之后就必須全是a
另外,.
無法匹配換行符??赡苣悴惶斫鉃槭裁葱枰ヅ鋼Q行符,它主要用在:
/^a.*\nb.*/
中括號表示的是匹配任意一個,一般它和字符集的排序規(guī)則有關(guān),不同工具采取的排序規(guī)則可能也不一樣。
[abcd...]
:匹配中括號內(nèi)的任意一個字符[^abcd...]
:拒絕匹配中括號內(nèi)的任意字符[a-z]
:匹配字母a到z[A-Z]
:匹配字母A到Z[0-9]
:匹配0-9,也就是匹配數(shù)字關(guān)于字母的排序:
是專門命名的中括號序列;除了字符類,還有等價類、排序類,但基本用不上,只用字符類。
[:alpha:]
:匹配字母,等價于[a-zA-Z]
[:digit:]
:匹配數(shù)字,等價于[0-9]
[:xdigit:]
:匹配十六進制數(shù),等價于[0-9a-fA-F]
[:upper:]
:匹配大寫字母,等價于[A-Z]
[:lower:]
:匹配小寫字母,等價于[a-z]
[:alnum:]
:匹配數(shù)字或字母,等價于[0-9a-zA-Z]
[:blank:]
:匹配空白,包括空格和制表符[:space:]
:匹配空格,包括空格、制表符、換行符、回車符等各種類型的空白[:punct:]
:匹配標點符號。包括:! ' " ` # $ % & ( ) * + , . - _ / : ; < = > ? @ [ \ ] ^ { | } ~
[:graph:]
:繪圖類。包括:大小寫字母、數(shù)字和標點符號。等價于[:alnum:]
+[:punct:]
[:print:]
:打印字符類。包括:大小寫字母、數(shù)字、標點符號和空格。等價于[:alnum:]
+[:punct:]
+space[:cntrl:]
:控制字符類。在ASCII中,這些字符的八進制代碼從000到037,還包括177(DEL)需要注意的是,通常字符類在真正使用過程中,會再加上一個中括號,例如[[:alpha:]]
。之所以如此,是因為這些字符類只是一種命名好的字符集合。例如[:lower:]
對應(yīng)的字符集合是a-z,而不是[a-z]
,所以要想讓其表示這些命名字符類中的任一字符,需要再加上一層括號[[:lower:]]
,它才等價于[a-z]
??赡軙兄诶斫馐褂米址惖臅r候為什么要加兩個中括號的例子是[^[:lower:]]
,它表示不包含任何小寫字母。
不同的工具,同一工具不同的版本,支持的反斜線序列能力不同。以下列出了部分常見序列。
以下所說的單詞,一般來說只包含數(shù)字、字母和下劃線,即[_0-9a-zA-Z]
。
以下幾種反斜線序列,基本上所有工具都支持:
\b
:匹配單詞邊界處的空字符\B
:匹配非單詞邊界處的空字符\<
:匹配單詞開頭處的空字符\>
:匹配單詞結(jié)尾處的空字符\w
:匹配單詞構(gòu)成部分,等價于[_[:alnum:]]
\W
:匹配非單詞構(gòu)成部分,等價于[^_[:alnum:]]
以下幾種,有些工具不支持,但perl都支持:
\s
:匹配空白字符,等價于[[:space:]]
\S
:匹配非空白字符,等價于[^[:space:]]
\d
:匹配數(shù)字,等價于[0-9]
\D
:匹配非數(shù)字,等價于[^0-9]
由于元字符.
默認無法匹配換行符,所以需要匹配換行符的時候,可以使用特殊組合[\d\D]
來替換.
,換句話說,如果想匹配任意長度的任意字符,可以換成[\d\D]*
,當然,前提是必須支持\d
和\D
兩個反斜線序列。
基礎(chǔ)正則中,使用括號可以對匹配內(nèi)容進行分組并暫時保存,分組后會有分組編號,可以使用反斜線加編號\N
的方式反向引用這些分組。
分組編號的方式是從左向右計算括號數(shù),無論如何嵌套,第一個左括號對應(yīng)的分組一定是編號1,用\1
來引用,第二個左括號對應(yīng)的分組一定是編號2,用\2
來引用,依此類推。
例如grep的分組捕獲:匹配兩個連續(xù)相同的字母。
echo "abcddefg" | grep -E "(.)\1"
可以認為分組就是變量賦值的過程。例如,上面示例的匹配過程如下:
1.匹配第一個字母a,放進分組,即賦值給變量(假設(shè)變量名為$1),即$1="a"
,再繼續(xù)執(zhí)行正則表達式匹配過程的反向引用,它引用的是$1,于是表示第一個字母a后面還要是字母a,于是匹配失敗。
2.匹配第二個字母b,放進分組,即$1="b"
,再匹配后一個字母,于是匹配失敗。
3.字母c同樣如此。
4.匹配字母d,放進分組,即$1="d"
,再匹配后一個字母,發(fā)現(xiàn)匹配成功,于是$1被保存下來。
5.已經(jīng)匹配成功,于是結(jié)束。
對于只使用基礎(chǔ)正則的工具來說,一般都只能引用\1
到\9
共9個反向引用,最多自己額外提供一個所有表示匹配內(nèi)容的反向引用(例如sed提供的&
)。對于超出10個的分組,使用基礎(chǔ)正則的工具一般來說是無能為力的。
再者,基礎(chǔ)正則僅僅只是將分組匹配到的內(nèi)容捕獲,在正則操作結(jié)束后就丟失。但對于一門完整編程語言來說,這遠遠不夠,幾乎所有編程語言(如perl/java/Python等)都會將正則的分組匹配內(nèi)容保存為變量,使得可以在正則結(jié)束之后再次引用甚至修改它們。例如上面例子中分組捕獲的字母d,如果換成perl,即使在這個匹配過程結(jié)束后,還是可以去引用這段分組。
pattern1 | pattern2
:匹配豎線左邊,或者匹配豎線右邊都算匹配成功關(guān)于二選一的結(jié)構(gòu),幾點需要說明:
ab|cd
匹配的是"ab"或"cd",而不是abd或acd。在二選一結(jié)構(gòu)種,兩個反向引用問題的典型例子:
例如a(.)|b\1
將無法匹配"ba",因為評估了左邊就不會評估右邊。
例如([ac])e\1|b([xyz])\2t
的左邊能匹配aea或cec,但不能匹配cea或aec,右邊能匹配bxxt或byyt或bzzt。但如果將\2
換成\1
,即([ac])e\1|b([xyz])\1t
,將無法匹配b[xyz]at或b[xyz]ct,因為第一個分組括號在左邊,無法參與右邊的正則評估。
聯(lián)系客服