半小時學會正則表達式(上)

半小時學會正則表達式(上)

正則表達式(Regular Expression)在代碼中常常簡寫為regex。正則表達式通常被用來檢索、替換那些符合某個規則的文本,它是一種強大而靈活的文本處理工具。

正則描述了一個規則,通過這個規則可以匹配一類字符串。

如何學習正則?

1、學習正則表達式的語法規則
2、練習使用正則并能解決實際問題

針對上面的每個點我會分別寫一篇文章來說明,用最短的時間學會正則表達式。

這篇文章講述正則表達式的語法和使用說明,讓你半小時學會正則表達式。

學習正則表達式語法,主要就是學習元字符以及它們在正則表達式上下文中的行為。

為了便于理解,文章所有示例的正則表達式用“regex=正則”表示,“=”號后面就是正則表達式,匹配到的字符會用顏色標注出來,連續匹配到的字符用一深一淺兩種顏色區分。比如:regex=\d+,其中\d+就是一個正則,它匹配任意多于1個的數字,如下:

regex=\d+匹配的字符串

正則表達式語法匯總

元字符:
普通字符、標準字符、特殊字符、限定字符(量詞)、定位字符(邊界字符)。

普通字符:
字母[a-zA-Z]、數字[0-9]、下劃線[-]、漢字,標點符號

匹配字母a可以regex=a
匹配字母b可以regex=b
匹配字母a或者b可以regex=a|b,這個正則引入一個特殊字符“|”,專業名稱為“或”,你也可以叫它“豎線”,總之它表示“或”的意思。

匹配字母a或者b或者c可以regex=a|b|c
匹配字母a或者b或者c或者d可以regex=a|b|c|d
明顯發現這么寫有點傻了,如果匹配所有26個字母,這種寫法就太二了。

這里引入兩個特殊字符方括號“[ ]”和中劃線“-”
“[ ]”,專業名稱為“字符集合”,你也可以叫它“方括號”。
“-”,表示“范圍”,你也可以叫它“到”,regex=[a-z]匹配從a到z26個字母的任意一個。

那么匹配字母a或者b或者c或者d可以regex=[abcd]
匹配數字1到8的任意數字可以regex=[1-8],這樣就不會匹配到0與9這2個數字了,如下:

regex=[1-8]匹配的字符串

標準字符集合:
標準字符集合是能夠與“多種普通字符”匹配的簡單表達式,比如:\d、\w、\s

匹配數字0到9的任意數字可以regex=[0-9]也可以regex=\d
標準字符集要注意區分大小寫,大寫是相反的意思
regex=\D,則匹配非數字字符,即不能匹配數字0到9,如下:

regex=\D匹配的字符串

下面是一些常用的標準字符說明

標準字符 含義
\d 匹配0-9中的任意一個數字,等效于[0-9]
\D 匹配非數字字符,等效于[^0-9]
\w 匹配任意一個字母、數字或下劃線,等效于[^A-Za-z0-9_]
\W 與任何非字母、數字或下劃線字符匹配,等效于[^A-Za-z0-9_]
\s 匹配任何空白字符,包括空格、制表符、換頁符,等效于 ?[\f\n\r\t\v]
\S 匹配任何非空白字符,等效于[^\f\n\r\t\v]
\n 匹配換行符
\r 匹配一個回車符
\t 匹配制表符
\v 匹配垂直制表符
\f 匹配換頁符

特殊字符:
這些字符在正則表達式中表示特殊的含義,比如:*,+,?,\,等等

“\”是轉義字符,用于匹配特殊字符

匹配反斜杠“\”可以regex=\\,因為“\”是特殊字符,所以需要在它前邊再加一個“\”進行轉義

匹配星號“*”,可以regex=\*,因為“*”是特殊字符,所以需要在它前邊再加一個“\”進行轉義

下面是一些常用的特殊字符說明,后面都會講到

特殊字符 含義
\ 轉義字符,將下一個字符標記為一個特殊字符
^ 匹配字符串開始的位置
$ 匹配字符串結尾的位置
* 零次或多次匹配前面的字符或子表達式
+ 一次或多次匹配前面的字符或子表達式
? 零次或一次匹配前面的字符或子表達式
. “點” 匹配除“\r\n”之外的任何單個字符
|
[ ] 字符集合
( ) 分組,要匹配圓括號字符,請使用 “(” ?或 “)”

限定字符(量詞)
限定字符又叫量詞,是用于表示匹配的字符數量的。

匹配任意1位數字可以regex=\d
匹配任意2位數字可以regex=\d\d
匹配任意3位數字可以regex=\d\d\d

匹配任意16位數字,再這么寫就有點傻了
這里引入用于表示數量限定字符“{n}”
{n},n是一個非負整數,匹配確定的n次

注意:regex=\d\d{3}匹配任意4個數字不是6個,量詞只對它前面的字符負責,regex=\d\d{3}匹配的內容如下:

regex=\d\d{3}匹配的字符串

匹配任意16位數字可以regex=\d{16}
匹配任意16位以上的數字可以regex=\d{16,}
匹配任意1到16位以上的數字可以regex=\d{1,16}

regex=\d{1,16}匹配到的字符串

從上圖,我們可以看到regex=\d{1,16},可以匹配到任意1-16個數字

下面介紹一下匹配次數中的貪婪模式與非貪婪模式

正則的匹配默認是貪婪模式,即匹配的字符越多越好,
非貪婪模式是匹配的字符越少越好,在修飾匹配字數的量詞后再加上一個問號“?”即可。

那么同樣是上面的字符串,regex=\d{1,16}?匹配到什么呢?

regex=\d{1,16}?匹配到的字符串

因為在{1,16}這個量詞后面加上了問號“?”,表示非貪婪模式,所以只能匹配到1個數字,即匹配的字符越少越好。

下面是一些常用的限定字符說明

限定字符 含義
* 零次或多次匹配前面的字符或子表達式
+ 一次或多次匹配前面的字符或子表達式
? 零次或一次匹配前面的字符或子表達式
{n} n是一個非負整數,匹配確定的n次
{n,} n是非負整數,至少匹配n次
{n,m} n和m是非負整數,其中n<=m;匹配至少n次,至多m次

匹配0個或多個字母A可以regex=A*或者regex=A{0,}
匹配至少一個字母A可以regex=A+或者regex=A{1,}
匹配0個或1字母A可以regex=A?或者regex=A{0,1}

匹配至少一個LOVE可以regex=(LOVE)+,匹配的效果如下:

regex=(LOVE)+匹配到的字符串

定位字符(字符邊界)
定位字符也叫字符邊界,標記匹配的不是字符而是符合某種條件的位置,所以定位字符是“零寬的”。

下面是一些常用的定位字符說明

定位字符 含義
^ 匹配字符串開始的位置,表示開始
$ 匹配字符串結尾的位置,表示結尾
\b 匹配一個單詞邊界

匹配以Hello開頭的字符串可以regex=^Hello

regex=^Hello匹配到的字符串

匹配以Hello結尾的字符串可以regex=Hello$,如下:

regex=Hello$匹配到的字符串

匹配以H開頭以o結尾的任意長度字符串可以regex=^H.*o$,如下:

regex=^H.*o$匹配到的字符串

\b匹配這樣一個位置:前面的字符和后面的字符不全是\w
如果在“hello,hello1 hello hello1 bhello”這個字符串里匹配regex=hello\b,
匹配到的結果如下:

regex=hello\b匹配到的字符串

分析一下:為什么hello1匹配不了“hello\b”這個正則?

首先\b是一個定位字符,它是零寬的,標識一個位置,這個位置的前面和這個位置的后面不能全是\w,即不能全是字母數字和下劃線[A-Za-z0-9_],而hello1的o與1之間的位置前面是o后面是1,前后全是\w,不符合\b匹配的含義,因此hello1不能匹配正則表達式“hello\b”

但是bhello可以匹配“hello\b”這個正則,因為hello的結尾的位置,前面是o,后面是空白,所以符合\b匹配的含義,因此bhello可以匹配“hello\b”這個正則。

自定義字符集合:
方括號[ ]表示字符集合,即[ ]表示自定義集合,用[ ]可以匹配方括號里的任意一個字符。

regex=[aeiou]匹配“a”,“e”,“i”,“o”,“u”任意一個字符,也就是可以匹配集合[aeiou]的任意一個字符。

但是,特殊字符(除了小尖角“^和中劃線“-)被包含到方括號中,就會失去特殊意義,只代表其字符本身。

regex=[abc+?]匹配“a”,“b”,“c”任意一個字符或者“+”,“*”,“?”,即包含在自定義集合中的特殊字符“+”,“*”,“?”*失去了特殊含義,只表示其字符本身的意思。

特殊字符小尖角“^”,原本含義是匹配字符串的開始位置,如果包含在自定義集合[ ]中,則表示取反的意思。
比如:regex=[^aeiou]匹配“a”,“e”,“i”,“o”,“u”之外的任意一個字符。

中劃線“-”,在自定義集合[ ]中,表示“范圍”,而不是字符“-”本身,regex=[a-z],匹配從a到z中26個字母的任意一個。

除小數點“.”外,標準字符集合包含在方括號中,仍然表示集合范圍。
regex=[\d.+]匹配0-9的任意一個數字或者小數點“.”或者加號“+”

也就是說\d在自定義集合中仍然表示數字,但是小數點在字符集合中只表示小數點本身,而不是除“\r\n”之外的任何單個字符。

選擇符和分組

表達式 作用
pattern1|pattern2 或的關系,匹配左邊的pattern1或右邊的pattern2
(pattern) 匹配pattern并獲取這一匹配,并存儲
(?:pattern) 匹配pattern但不獲取匹配結果,也就是不進行存儲

regex=x|y,匹配字符x或y。

( )表示捕獲組,( )的作用如下:
1、括號中的表達式可以作為整體被修飾,用來表示匹配括號中表達式的次數,regex=(abc){2,3},可以匹配連續的2個或3個abc,如下:

regex=(abc){2,3}匹配到的字符串

2、括號中的表達式匹配到的內容會存儲起來,并可以獲取到括號中表達式匹配到的內容
3、每一對括號會分配一個編號,使用( )的捕獲根據左括號的順序從1開始自動編號,編號為0的捕獲是整個正則表達式匹配到的文本。

捕獲組( )可以把匹配的內容存儲起來,那么如何獲取( )捕獲到的內容呢,下面介紹反向引用。

反向引用“\number”
每一對括號會分配一個編號,使用( )的捕獲根據左括號的順序從1開始自動編號。通過反向引用,可以對分組已捕獲的字符串進行引用。
“\number”中的number就是組號

regex=(abc)d\1可以匹配字符串abcdabc,即\1表示把獲取到的第一組再匹配一次,如下:

regex=(abc)d\1匹配到的字符串

(?:pattern)表示非捕獲組,匹配括號中表達式匹配到的內容,但是不進行存儲匹配到的內容。這在使用 "或" 字符?(|)?來組合一個正則的各個部分是很有用的。

例如:匹配字符“story”或者“stories”,regex=stor(?:y|ies)就是一個比 regex=story|stories更簡略的表達式。

預搜索(零寬斷言)
預搜索,又叫零寬斷言,又叫環視,它是對位置的匹配,與定位字符(邊界字符)類似。

表達式 作用
(?=pattern) 斷言此位置的后面能匹配表達式pattern
(?<=pattern) 斷言此位置的前面能匹配表達式pattern
(?!pattern) 斷言此位置的后面不能匹配表達式pattern
(?<!pattern) 斷言此位置的前面不能匹配表達式pattern

regex=love (?=story)匹配的結果如下(匹配“love?”后面是story):

regex=love (?=story)匹配到的字符串

regex=love (?!story)匹配的結果如下(匹配“love ”后面不能是story):

regex=love (?!story)匹配到的字符串

運算符的優先級
正則表達式從左到右進行計算,并遵循優先級順序,這與算術表達式非常類似。

下表的優先級從高到低排序

運算符 描述
\ 轉義字符
(), (?:), (?=), [] 圓括號和方括號,分組和自定義集合
*, +, ?, {n}, {n,}, {n,m} 限定字符(量詞)
^, $, 標準字符,字符 定位字符(邊界字符)和字符
|

說明:“|”或操作是優先級最低的,它比普通字符的優先級低。
因此,regex=r|loom匹配“r”或“loom”,如下:

regex=r|loom匹配到的字符串

如果想匹配“room”或“loom”,請用括號創建子表達式,regex=(r|l)oom,如下:

regex=(r|l)oom匹配到的字符串

至此,正則表達式的語法介紹完了,大家是不是已經掌握了呢,趕快去體驗一下吧。

最后給大家介紹一下開發中使用正則表達式的流程:
1、分析所要匹配的數據特點,模擬各種測試數據;
2、利用正則工具,寫正則表達式與測試數據進行匹配,從而驗證你寫的正則;
3、在程序里調用在正則工具中驗證通過的正則表達式。

在這里給大家推薦一個正則工具“RegexBuddy”,你可以從網上下載,或者回復關鍵詞“正則表達式”獲取。

《半小時學會正則表達式(下)》會講解學習正則表達式的第二部分,練習使用正則并解決一些實際問題,敬請關注后續內容。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 正則表達式到底是什么東西?字符是計算機軟件處理文字時最基本的單位,可能是字母,數字,標點符號,空格,換行符,漢字等...
    獅子挽歌閱讀 2,178評論 0 9
  • 推薦幾個正則表達式編輯器 Debuggex :https://www.debuggex.com/ PyRegex:...
    木易林1閱讀 11,555評論 9 151
  • 注:本篇文章只為方便查看,特此保留,如有冒犯,敬請諒解?。。?本文目標 30分鐘內讓你明白正則表達式是什么,并對它...
    阿杰Alex閱讀 1,508評論 0 10
  • 初衷:看了很多視頻、文章,最后卻通通忘記了,別人的知識依舊是別人的,自己卻什么都沒獲得。此系列文章旨在加深自己的印...
    DCbryant閱讀 4,071評論 0 20
  • 幾個正則表達式編輯器 Debuggex :https://www.debuggex.com/ PyRegex:ht...
    沒技術的BUG開發攻城獅閱讀 4,622評論 0 23