1. 概要
Perl正則表達式是Boost.regex 默認行為,也可以將perl傳入basic_regex 構造。
boost::regex e1(my_expression);
boost::regex e2(my_expression, boost::regex::perl | boost::regex::icase);
2. 特殊字符
. [ { ( ) \ * + ? | ^ $
3. 通配符 ‘ .’
在字符集之外使用時可以匹配任意單字符,除了以下兩種特殊情況:
(1)NULL字符,當 標記 match_not_dot_null 被傳入匹配算法中時。
(2)換行字符,當 標記 match_not_dot_newline 被傳入匹配算法中時。
4. 錨點
'^'字符會匹配行的起始。
'$'字符會匹配行的終止。
5. 標記子表達式
在()之間的部分是被標記的字表達式,匹配算法會將子表達式匹配的部分分離成獨立的部分。 標記子表達式可以被重復,或后向引用。
6.非標記組
標記子表達式對於正則表達式中的成組文字部分是非常有用的,但將結果分組是有副作用的。 作為選擇,可以通過 (?: expression ) 產生文字分組,但不產生標記子表達式,例如 (?:ab)+ 會重復 ab 但並不分隔出單獨的子表達式。
7. 重復
任意原子(單個字符,一個標記子表達式或一個字符組)可以通過 *, +, ? 和 {} 操作符重復。
操作符 |
說明 |
* |
匹配前面的原子零次或多次 |
+ |
匹配前面的原子一次或多次 |
? |
匹配前面的原子零次或一次 |
{n} |
匹配前面的原子n次 |
{n,} |
匹配前面的原子n次或更多次 |
{n,m} |
匹配前面的原子n次到m次之間 |
注:如果前面的結構不能被重復,那么使用重復操作符是一個錯誤:
如:a(*) 會報告一個錯誤。
8.非貪婪重復
語法 |
說明 |
*? |
匹配前面的原子零次或多次,但盡可能少地消耗輸入 |
+? |
匹配前面的原子一次或多次,但盡可能少地消耗輸入 |
?? |
匹配前面的原子零次或一次,但盡可能少地消耗輸入 |
{n,}? |
匹配前面的原子n次或更多次,但盡可能少地消耗輸入 |
{n,m}? |
匹配前面的原子n次到m次,但盡可能少地消耗輸入 |
9. Pocessive 重復
缺省情況下,當一個重復模式不能被匹配時,引擎將回溯直至找到一個匹配。但是,有時候這種行為不是用戶所期望的, 因此還有一種"pocessive"重復:它盡可能多地進行匹配且當剩下的表達式不能匹配時不允許進行回溯。
語法 |
說明 |
*+ |
匹配前面的原子零次或多次,但不退回 |
++ |
匹配前面的原子一次或多次,但不退回 |
?+ |
匹配前面的原子零次或一次,但不退回 |
{n,}+ |
匹配前面的原子n次或多次,但不退回 |
{n,m}+ |
匹配前面的原子n次到m次,但不退回 |
10. 后向引用
(1)一個轉義字符跟着一個數字\n,n的范圍是1-9,匹配被子表達式 n 匹配的相同字符串,如:
^(a*).*\1$ 匹配 aaabbaaa 但不匹配 aaabba
(2)\g轉義符:
語法 |
說明 |
\g1 |
匹配字表達式1的內容 |
\g{1} |
匹配字表達式1的內容:更安全的方式如\g{1234} 或\g{1}2 |
\g-1 |
匹配最后一個被打開的字表達式的內容 |
\g{-2} |
匹配倒數第二個被打開的子表達式的內容 |
\g{one} |
匹配名為“one”的字表達式的內容 |
(3)\k轉義符可用於引用命名子表達式,如\k<two>將匹配名為“two”的子表達式的內容
11. 選擇
(1)| 操作符匹配它的參數之一,例如 abc|def 會匹配“abc”或“def”
(2)括號可以用來對選擇進行分組,例如:ab(d|ef) 會匹配 "abd" 或 "abef"。
(3)空的選擇是不允許的(這通常都是錯誤),但如果真的需要一個空的選擇,可以使用 (?:) 作為占位符,如:
|abc 不是有效的表達式,但
(?:)|abc 是有效的表達式,並且與以下表達式:
(?:abc)?? 有完全相同的作用
12. 字符集
字符集是一個[]方括號表達式,它定義了一個字符的集合,匹配集合中的任意單個字符。包含下面的組合:
(1)單個字符:如[abc]可以匹配’a’, ’b’, 或 ’c’。
(2)字符范圍:如[a-c]可以匹配’a’ 到 ’c’范圍內的任意單個字符。
對於缺省的Perl正則表達式, 如果字符x的編碼值在范圍兩端字符y和z的編碼值之間,就稱字符x在范圍y到z的中間。
另外,如果在構造正則表達式時設置了 collate 標記, 那范圍就是locale相關的。
(3)否定:如果方括號表達式以 ^ 字符開始,那么它匹配包含字符的補集,如:[^a-c]匹配不在a到c范圍內的任意字符。
(4)字符類
形如 [[:name:]] 的表達式匹配命名字符類"name",例如 [[:lower:]] 任意小寫字符。 參見字符類名稱表。
(5)對照元素
形如 [[.col.]] 的表達式匹配對照元素 /col/。對照元素是任意的單個字符,或對應於某個單個單元的字符序列。 對照還可以用作范圍的端點,例如 [[.ae.]-c] 匹配字符序列"ae",和任意的單個字符在范圍"ae"到c之間, 其中"ae"被當前locale處理為單個對照元素。
作為擴展,對照元素可以通過其 符號名 指定,例如:
[[.NUL.]] 匹配一個 \0 字符。
(作為對照元素名稱時下面的情況被當作合法的連字:
"ae", "Ae", "AE", "ch", "Ch", "CH", "ll", "Ll", "LL", "ss", "Ss", "SS", "nj", "Nj", "NJ", "dz", "Dz", "DZ", "lj", "Lj", "LJ". )
(6)等價類
形如 [[=col=]] 的表達式匹配主排序關鍵字等同於對照元素 col 的任意字符或對照元素,其中名字為 col 的對照元素可以是一個 符號名。主排序關鍵字忽略大小寫、重音或特定區域(locale)的裁剪(tailorings); 所以如 [[=a=]] 匹配下面的字符:a, À, Á, Â, Ã, Ä, Å, A, à, á, â, ã, ä 和 å。 不幸的是這個實現依賴於平台的對照(collation)和地區(localization)支持; 這個特性並不能很好地可移植工作於所有的平台,甚至一個平台上的所有區域(locale)。
(7)轉義字符
任意匹配單個字符或單個字符類的轉義序列都可以定義在字符類中。例如[\[\]] 可以匹配 [ 或 ] ,而 [\W\d] 可以匹配任何“數字”字符或者任何不是"單詞"的字符。
(8)組合
所有上面的都可以在一個字符類聲明中被組合,例如 [[:digit:]a-c[.NUL.]]。
13. 轉義符
(1)任意特殊字符前面加轉義符都匹配自己。
(2)下面的轉義序列和單個字符同義
轉義符 |
字符 |
\a |
\a |
\e |
0x1B |
\f |
\f |
\n |
\n |
\r |
\r |
\t |
\t |
\v |
\v |
\b |
\b(僅在字符類聲明中使用) |
\cX |
一個ASCII轉義序列,字符碼點為 X % 32 |
\xdd |
一個十六進制轉義序列,匹配碼點為0xdd的單個字符。 |
\x{dddd} |
一個十六進制轉義序列,匹配碼點為0xdddd的單個字符。 |
\0ddd |
八進制轉義序列,匹配碼點為0ddd的單個字符。 |
\N{name} |
匹配 符號名 為name的單個字符。 |
(3)“單字符” 字符類
轉義序列 |
等價於 |
\d |
[[:digit:]] |
\l |
[[:lower:]] |
\s |
[[:space:]] |
\u |
[[:upper:]] |
\w |
[[:word:]] |
\h |
水平空白 |
\v |
垂直空白 |
\D |
[^[:digit:]] |
\L |
[^[:lower:]] |
\S |
[^[:space:]] |
\U |
[^[:upper:]] |
\W |
[^[:word:]] |
\H |
非水平空白 |
\V |
非垂直空白 |
(4)字符屬性
下面表格中的字符屬性名稱都等價於字符類中使用的名字。
形式 |
說明 |
等價的字符集形式 |
\pX |
匹配任意具有屬性X的字符 |
[[:X:]] |
\p{Name} |
匹配任意具有屬性Name的字符 |
[[:Name:]] |
\PX |
匹配任意不具有屬性X的字符 |
[^[:X:]] |
\P{Name} |
匹配任意不具有屬性Name的字符 |
[^[:Name:]] |
例如 \pd 匹配任意的"數字"字符,和 \p{digit} 作用是一樣的。
(5)單詞邊界
下面的轉義序列匹配單詞的邊界:
\< 匹配單詞的起點
\>匹配單詞的終點
\b匹配單詞的邊界(起點或終點)
\B只有不在邊界時才匹配。
(6)緩沖區邊界
下面的轉義序列匹配緩沖區邊界:這里的"緩沖區"指用於匹配的全部輸入文本(注意,^和$可以用於匹配文本中的行)。
\` 匹配緩沖區的起點。
\' 匹配緩沖區的終點。
\A 匹配緩沖區的起點(同 \\\` 一樣)。
\z 匹配緩沖區的終點(同 \\' 一樣)。
\Z 匹配一個零長度的斷言,包括緩沖區結尾處可能存在的空行:等價於正則表達式 (?=\v*\z)。注意,這與 Perl 中匹配 (?=\n?\z) 的行為有一些微妙的不同。
(7)持續轉義
序列 \G 只在上次匹配結尾或匹配文本的起點(如果前面沒有匹配)。 當你要迭代文本中所有的匹配,並且每個子序列都從上一次結束時開始匹配的話,這個轉義是很有用的。
(8)引用轉義
轉義序列 \Q 開始一個"被引用序列":所有后面的字符都被當作字面對待,除非正則表達式結束或碰到 \E。 例如,表達式:\Q\*+\Ea+ 可以匹配如下:
\*+a
\*+aaa
(9)Unicode轉義
\C 匹配一個單一的碼表:在 Boost.Regex 中這和"."操作符的作用是完全相同的。
\X 匹配一個組合字符序列:任意非組合字符跟上一個零或多個組合字符的序列。
(10)匹配行末符
轉義序列 \R 匹配任何行末符序列,特別地,它等同於表達式 (?>\x0D\x0A?|[\x0A-\x0C\x85\x{2028}\x{2029}]).
(11)回退一些文本
\K 將$0的開始位置重置為當前文本位置:換言之,\K 左邊的所有東西被"退回"且不作為該正則表達式的匹配部分。 $` 也被相應更新。
例如,foo\Kbar 用於匹配文本 "foobar" 時,將對 $0 返回匹配 "bar",對 $` 返回 "foo"。 這可以被用於模擬可變寬度的后向環視斷言。
(12)其他轉義
其它轉義序列匹配被轉義的字符,例如 \@匹配 '@'。
14. Perl 擴展模式
Perl擴展的正則表達式語法都以 (? 開始。
(1)命名子表達式: (?<NAME>expression),或者 (?'NAME'expression)
(2)引用命名子表達式: 通過\g{NAME} 或 \k<NAME>后向引用,也可以在一個 Perl 格式化串或在 match_results 成員函數中通過名字來引用以進行搜索和替換的操作。
(3)注釋
(?# ... ) 作為注釋,里面的內容被忽略。
(4)修飾
(?imsx-imsx ... ) 改變在模式中perl修飾符是否起作用,從塊第一次被遇到的點開始起作用,直到遇到結束 =)=。 '-' 之前的字母打開perl修飾符,后面的字母關閉。
(?imsx-imsx:pattern) 只將特定的修飾符應用於指定的模式。
(5)非標記分組
(?:pattern) 進行字面分組,但不產生額外的子表達式。
(6)分支重置
(?|pattern) 在 pattern 內的每個 "|" 選擇符開始重置子表達式計數。
該結構之后的子表達式計數由具有最大子表達式數量的分支決定。當你想用單個子表達式索引捕獲多個可選匹配之一的時候,可使用該結構。例如:
/ ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x
# 1 2 2 3 2 3 4
(7)前向匹配
(?=pattern) 當模式匹配時成功,但不消耗字符
(?=exp)也叫“零寬度正預測先行斷言”,它斷言自身出現的位置的后面能匹配表達式exp,比如\b\w+(?=ing\b),匹配以ing結尾的單詞的前面部分(除了ing以外的部分),如查找I'm singing while you're dancing.時,它會匹配sing和danc。
(?!pattern) 當模式不匹配時成功,但不消耗字符。
“零寬度負預測先行斷言”(?!exp),斷言此位置的后面不能匹配表達式exp。例如:\d{3}(?!\d)匹配三位數字,而且這三位數字的后面不能是數字;\b((?!abc)\w)+\b匹配不包含連續字符串abc的單詞。
前向匹配的典型用法是創建兩個正則表達式的邏輯與,例如一個密碼必須包含一個小寫字符, 一個大寫字符,一個標點符號,長度至少6個字符,那么表達式是:
(?=.*[[:lower:]])(?=.*[[:upper:]])(?=.*[[:punct:]]).{6,}
(8)后向匹配
(?<=pattern) 只有當模式能夠被當前位置之前的字符匹配時才成功(模式必須是固定長度),但並不消耗字符。
(?<=exp)也叫“零寬度正回顧后發斷言”,它斷言自身出現的位置的前面能匹配表達式exp。比如(?<=\bre)\w+\b會匹配以re開頭的單詞的后半部分(除了re以外的部分),例如在查找reading a book時,它匹配ading。
(?<!pattern) 只有當模式不能夠被當前位置之前的字符匹配時才成功(模式必須是固定長度),但並不消耗字符。
“零寬度負回顧后發斷言” (?<!pattern),來斷言此位置的前面不能匹配表達式exp:(?<![a-z])\d{7}匹配前面不是小寫字母的七位數字
(9)獨立子表達式
(?>pattern) pattern 獨立於外圍模式地被匹配,表達式決不會被回溯到 pattern 中。 獨立子表達式通常用於改善性能;只有最好可能的匹配才會被考慮,如果表達式不能作為整體被匹配,那就沒有匹 配。
(10)遞歸表達式
(?N) (?-N) (?+N) (?R) (?0)
(?R) and (?0) 遞歸至整個模板的開始。
(?N) 重復執行子表達式/N/,例如 (?2) 將遞歸至子表達式2。
(?-N) 和 (?+N) 是相對遞歸,因此如 (?-1) 將遞歸至被聲明的最后一個子表達式,而 (?+1) 則遞歸至被聲明的下一個子表達式。
(11)條件表達式
1. (?(condition)yes-pattern|no-pattern) 當 condition 成立時試圖匹配 /yes-pattern/,否則試圖匹配 /no-pattern/。
2. (?(condition)yes-pattern) 當 condition 成立時試圖匹配 /yes-pattern/,否則直接失敗。
3. condition 可以是一個前向匹配斷言, 或者是一個標記子表達式序號(當子表達式匹配時條件為真), 或是一個遞歸的索引(當我們在指定遞歸中直接執行時條件為真)。
4. 可能的謂詞:
(?(?=assert)yes-pattern|no-pattern) 如果前向匹配成功則執行 /yes-pattern/,否則執行 /no-pattern/。
(?(?!assert)yes-pattern|no-pattern) 如果前向匹配不成功則執行 /yes-pattern/,否則執行 /no-pattern/。
(?(R)yes-pattern|no-pattern) 如果是在某個遞歸的內部執行,則執行 /yes-pattern/,否則執行 /no-pattern/。
(?(RN)yes-pattern|no-pattern) 如果是在某個到子表達式/N/的遞歸內部執行,則執行 /yes-pattern/,否則執行 /no-pattern/。
(?(DEFINE)never-exectuted-pattern) 定義一個從不執行也不匹配任何字符的代碼塊: 通常用於定義一個或多個從模板其它地方引用的命名子表達式。
15. 操作符優先級
(1)對照相關的方括號字符 [==] [::] [..]
(2)轉義字符 \
(3)字符集(方括號表達式) []
(4)分組 ()
(5)單字符-ERE重復 * + ? {m,n}
(6)連接
(7)錨點 ^$
(8)選擇 |
16. 最優匹配
如果將正則表達式當作有向(可能循環)圖,那么最優匹配就是在匹配輸入文本過程中按照深度優先搜索找到的第一個匹配。
字符類名稱表:
名稱 |
是否POSIX標准名稱 |
說明 |
alnum |
yes |
任意 單詞-數字 字符 |
alpha |
yes |
任意單詞字符 |
blank |
yes |
非行分隔符的任意空白字符 |
cntrl |
yes |
任意控制字符 |
d |
no |
任意數字字符 |
digit |
yes |
任意數字字符 |
graph |
yes |
任意圖形字符 |
l |
no |
任意小寫字符 |
lower |
yes |
任意小寫字符 |
|
yes |
任意可打印字符 |
punct |
yes |
任意標點字符 |
s |
no |
任意空白字符 |
space |
yes |
任意空白字符 |
unicode |
no |
任意碼點高於255的字符 |
u |
no |
任意大寫字符 |
upper |
yes |
任意大寫字符 |
w |
no |
任意單詞字符(字母、數字和下划線)。 |
word |
no |
任意單詞字符(字母、數字和下划線)。 |
xdigit |
yes |
任意十六進制數字字符。 |
應用舉例:
[root@sh_proxy network-scripts]# curl -s -X POST -H 'Content-Type:application/json' -d '
{
"jsonrpc": "2.0",
"method": "user.login",
"params": {
"user": "Admin",
"password": "zabbix"
},
"id": 1
}' http://192.168.85.252/zabbix/api_jsonrpc.php
{"jsonrpc":"2.0","result":"203372ae31e9a06c4063a81f12c746e3","id":1}[root@sh_proxy network-scripts]#
[root@sh_proxy network-scripts]# curl -s -X POST -H 'Content-Type:application/json' -d '
{
"jsonrpc": "2.0",
"method": "user.login",
"params": {
"user": "Admin",
"password": "zabbix"
},
"id": 1
}' http://192.168.85.252/zabbix/api_jsonrpc.php | grep -Po 'result[" :]+\K[^"]+'
578fa15611f36a453a59d5908ceec2c2
[root@sh_proxy network-scripts]#
[root@blog ~ 11:23:59]$zabbix_get -s 127.0.0.1 -k net.if.in[eth0]
ZBX_NOTSUPPORTED: Cannot find information for this network interface in /proc/net/dev.
[root@blog ~ 11:24:24]$cat /proc/net/dev
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 4089618953 40612369 0 0 0 0 0 0 4089618953 40612369 0 0 0 0 0 0
virbr0-nic: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
virbr0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ens33: 6473256503 32704857 0 0 0 0 0 0 1421806421 15497584 0 0 0 0 0 0
[root@blog ~ 11:24:34]$zabbix_get -s 127.0.0.1 -k net.if.in[ens33]
6473272437
[root@blog ~ 11:24:53]$zabbix_get -s 127.0.0.1 -k net.if.in[ens33]
6473285466
[root@blog ~ 11:25:11]$zabbix_get -s 127.0.0.1 -k net.if.out[ens33]
1421839367
[root@blog ~ 11:25:21]$ifconfig ens33
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.85.252 netmask 255.255.255.0 broadcast 192.168.85.255
inet6 fe80::20c:29ff:fed2:b9b5 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:d2:b9:b5 txqueuelen 1000 (Ethernet)
RX packets 32705760 bytes 6473379085 (6.0 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 15498439 bytes 1421899001 (1.3 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@blog ~ 11:26:33]$ifconfig ens33 | grep -oP '(?<=ether )\S+' ## \s表空白字符, \S表示非空白字符
00:0c:29:d2:b9:b5
[root@blog ~ 11:28:04]$