基礎正則表示式詳述
本文介紹基礎正則表示式,沒有示例(),只有總結和"解惑",如果想學習更強大、更完整的正則,可以參考:Perl正則超詳細教程,grep -P
、ack都支援Perl正則,且很多需要使用到正則的服務軟體一般都採用PCRE(如httpd、nginx、haproxy、proxysql),它和Perl正則幾乎完全一致,作為運維人員,我覺得是有必要學上一學的。
基礎正則
元字元:
-
.
:匹配任意單個字元,但不能匹配換行符\n
-
*
:匹配前面那個字元0或多次 -
?
:匹配前面那個字元0或一次 -
+
:匹配前面那個字元1次以上 -
{M,N}
:匹配前面那個字元至少M,最多N次 -
{M,}
:匹配前面那個字元至少M次,最多無限制 -
{,N}
:匹配前面那個字元最多N次(最少當然是0次)。注意,perl正則不支援這種方式 -
{M}
:匹配前面那個字元正好M次 -
錨定:錨定的意思是匹配位置,而非匹配字元實體
^ $
特殊且常用的的組合正則表示式:
^$ .*
需要解釋清楚的是這些量詞(也就是上面匹配的次數元字元)的特殊性:當使用了匹配多次的量詞時(如匹配3-5次的{3,5}
),且量詞前面的字元有多種可能性(如中括號序列[abc]
),那麼量詞的次數可以作用於任一字元。有些不好理解,但看示例就知道了:
[abc]{3,5}# 表示abc任意字元都可以出現,比如全是a,或者ab同時出現,但總的出現次數為3-5次 .*# 表示任一字元(除換行符),可以任意出現任意次數,它不表示a之後就必須全是a .+# 表示任一字元(除換行符),可以任意出現至少一次,它不表示a之後就必須全是a
另外,.
無法匹配換行符。可能你不太理解為什麼需要匹配換行符,它主要用在:
/^a.*\nb.*/
中括號
中括號表示的是匹配任意一個,一般它和字符集的排序規則有關,不同工具採取的排序規則可能也不一樣。
[abcd...] [^abcd...] [a-z] [A-Z] [0-9]
關於字母的排序:
- perl中,A-Z排在a的前面,所以[A-z]表示所有大小寫字母
- grep中,A-Z排在z的後面,所以[a-Z]表示所有大小寫字母
- 還有些工具中,大小寫的排序規則是aAbBcC...zZ,所以[a-C]表示aAbBcC共6個字母
字元類
是專門命名的中括號序列;除了字元類,還有等價類、排序類,但基本用不上,只用字元類。
-
[:alpha:]
:匹配字母,等價於[a-zA-Z]
-
[:digit:]
:匹配數字,等價於[0-9]
-
[:xdigit:]
:匹配十六進位制數,等價於[0-9a-fA-F]
-
[:upper:]
:匹配大寫字母,等價於[A-Z]
-
[:lower:]
:匹配小寫字母,等價於[a-z]
-
[:alnum:]
:匹配數字或字母,等價於[0-9a-zA-Z]
-
[:blank:]
:匹配空白,包括空格和製表符 -
[:space:]
:匹配空格,包括空格、製表符、換行符、回車符等各種型別的空白 -
[:punct:]
:匹配標點符號。包括:! ' " ` # $ % & ( ) * + , . - _ / : ; < = > ? @ [ \ ] ^ { | } ~
-
[:graph:]
:繪圖類。包括:大小寫字母、數字和標點符號。等價於[:alnum:]
+[:punct:]
-
[:print:]
:列印字元類。包括:大小寫字母、數字、標點符號和空格。等價於[:alnum:]
+[:punct:]
+space -
[:cntrl:]
:控制字元類。在ASCII中,這些字元的八進位制程式碼從000到037,還包括177(DEL)
需要注意的是,通常字元類在真正使用過程中,會再加上一個中括號,例如[[:alpha:]]
。之所以如此,是因為這些字元類只是一種命名好的字元集合。例如[:lower:]
對應的字元集合是a-z,而不是[a-z]
,所以要想讓其表示這些命名字元類中的任一字元,需要再加上一層括號[[:lower:]]
,它才等價於[a-z]
。可能會更有助於理解使用字元類的時候為什麼要加兩個中括號的例子是[^[:lower:]]
,它表示不包含任何小寫字母。
反斜線序列
不同的工具,同一工具不同的版本,支援的反斜線序列能力不同。以下列出了部分常見序列。
以下所說的單詞,一般來說只包含數字、字母和下劃線,即[_0-9a-zA-Z]
。
以下幾種反斜線序列,基本上所有工具都支援:
-
\b
:匹配單詞邊界處的空字元 -
\B
:匹配非單詞邊界處的空字元 -
\<
:匹配單詞開頭處的空字元 -
\>
:匹配單詞結尾處的空字元 -
\w
:匹配單詞構成部分,等價於[_[:alnum:]]
-
\W
:匹配非單詞構成部分,等價於[^_[:alnum:]]
以下幾種,有些工具不支援,但perl都支援:
-
\s
:匹配空白字元,等價於[[:space:]]
-
\S
:匹配非空白字元,等價於[^[:space:]]
-
\d
:匹配數字,等價於[0-9]
-
\D
:匹配非數字,等價於[^0-9]
由於元字元.
預設無法匹配換行符,所以需要匹配換行符的時候,可以使用特殊組合[\d\D]
來替換.
,換句話說,如果想匹配任意長度的任意字元,可以換成[\d\D]*
,當然,前提是必須支援\d
和\D
兩個反斜線序列。
分組捕獲和反向引用
基礎正則中,使用括號可以對匹配內容進行分組並暫時儲存,分組後會有分組編號,可以使用反斜線加編號\N
的方式反向引用這些分組。
分組編號的方式是從左向右計算括號數,無論如何巢狀,第一個左括號對應的分組一定是編號1,用\1
來引用,第二個左括號對應的分組一定是編號2,用\2
來引用,依此類推。
例如grep的分組捕獲:匹配兩個連續相同的字母。
echo "abcddefg" | grep -E "(.)\1"
可以認為分組就是變數賦值的過程。例如,上面示例的匹配過程如下:
1.匹配第一個字母a,放進分組,即賦值給變數(假設變數名為$1),即$1="a"
,再繼續執行正則表示式匹配過程的反向引用,它引用的是$1,於是表示第一個字母a後面還要是字母a,於是匹配失敗。
2.匹配第二個字母b,放進分組,即$1="b"
,再匹配後一個字母,於是匹配失敗。
3.字母c同樣如此。
4.匹配字母d,放進分組,即$1="d"
,再匹配後一個字母,發現匹配成功,於是$1被儲存下來。
5.已經匹配成功,於是結束。
對於只使用基礎正則的工具來說,一般都只能引用\1
到\9
共9個反向引用,最多自己額外提供一個所有表示匹配內容的反向引用(例如sed提供的&
)。對於超出10個的分組,使用基礎正則的工具一般來說是無能為力的。
再者,基礎正則僅僅只是將分組匹配到的內容捕獲,在正則操作結束後就丟失。但對於一門完整程式語言來說,這遠遠不夠,幾乎所有程式語言(如perl/java/Python等)都會將正則的分組匹配內容儲存為變數,使得可以在正則結束之後再次引用甚至修改它們。例如上面例子中分組捕獲的字母d,如果換成perl,即使在這個匹配過程結束後,還是可以去引用這段分組。
二選一
-
pattern1 | pattern2
:匹配豎線左邊,或者匹配豎線右邊都算匹配成功
關於二選一的結構,幾點需要說明:
ab|cd
在二選一結構種,兩個反向引用問題的典型例子:
例如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,因為第一個分組括號在左邊,無法參與右邊的正則評估。
Linux公社的RSS地址 :ofollow,noindex" target="_blank">https://www.linuxidc.com/rssFeed.aspx
本文永久更新連結地址:https://www.linuxidc.com/Linux/2018-10/154659.htm