學(xué)習(xí)正則表達(dá)式的簡單方法

前言

分析數(shù)據(jù)的前提是要準(zhǔn)確提煉數(shù)據(jù),而正則表達(dá)式就是很好的提煉數(shù)據(jù)工具。

本文旨在讓讀者快速地了解正則表達(dá)式的基本規(guī)則和特性。本文雖說簡單,但其實(shí)也不簡單,需要反復(fù)觀看記憶。

本文轉(zhuǎn)載于資料[1],每個(gè)例子我基本都測試了一遍。也加了一些內(nèi)容和標(biāo)記,方便更好理解。

目錄

[TOC]

什么是正則表達(dá)式 ?

正則表達(dá)式是一種被用于從文本中檢索符合某些特定模式的文本。

正則表達(dá)式是從左到右來匹配一個(gè)字符串的。由于"Regular Expression" 這個(gè)詞太長了,我們通常使用它的縮寫 "regex" 或者 "regexp"。

正則表達(dá)式可以被用來替換字符串中的文本、驗(yàn)證表單、基于模式匹配從一個(gè)字符串中提取字符串等等。

想象一下,您正在編寫應(yīng)用程序,并且您希望在用戶選擇用戶名時(shí)設(shè)置規(guī)則。我們希望用戶名可以包含字母,數(shù)字,下劃線和連字符。為了讓它看起來不丑,我們還想限制用戶名中的字符數(shù)量。我們可以使用以下正則表達(dá)式來驗(yàn)證用戶名:

正則表達(dá)式

上面這個(gè)正則表達(dá)式可以匹配 john_doejo-hn_doejohn12_as。但是它不能匹配 Jo,因?yàn)樵撟址锩姘舜髮懽址?,并且它太短了?/p>

注:以下大部分例子為全局搜索,什么是全局搜索,請參考目錄5.2。

1. 基本匹配

正則表達(dá)式只是我們用于在文本中檢索字母和數(shù)字的模式。例如正則表達(dá)式 cat,表示: 字母 c 后面跟著一個(gè)字母 a,再后面跟著一個(gè)字母 t。

cat => The cat sat on the mat

正則表達(dá)式 123 會匹配字符串 "123"。通過將正則表達(dá)式中的每個(gè)字符逐個(gè)與要匹配的字符串中的每個(gè)字符進(jìn)行比較,來完成正則匹配。

正則表達(dá)式通常區(qū)分大小寫,因此正則表達(dá)式 Cat 與字符串 "cat" 不匹配。

Cat => The cat sat on the Cat

2. 元字符

元字符是正則表達(dá)式的基本組成元素。元字符在這里跟它通常表達(dá)的意思不一樣,而是以某種特殊的含義去解釋。有些元字符寫在方括號內(nèi)的時(shí)候有特殊含義。

元字符如下:

元字符 描述
. 匹配除換行符以外的任意字符。
[ ] 字符類,匹配方括號中包含的任意字符。
[^ ] 否定字符類。匹配方括號中不包含的任意字符
* 匹配前面的子表達(dá)式零次或多次
+ 匹配前面的子表達(dá)式一次或多次
? 匹配前面的子表達(dá)式零次或一次,或指明一個(gè)非貪婪限定符。
{n,m} 花括號,匹配前面字符至少 n 次,但是不超過 m 次。
(xyz) 字符組,按照確切的順序匹配字符xyz。
| 分支結(jié)構(gòu),匹配符號之前的字符后面的字符。
\ 轉(zhuǎn)義符,它可以還原元字符原來的含義,允許你匹配保留字符 [ ] ( ) { } . * + ? ^ $ \ |
^ 匹配行的開始
$ 匹配行的結(jié)束

2.1 英文句號

英文句號 . 是元字符的最簡單的例子。元字符 . 可以匹配任意單個(gè)字符。它不會匹配換行符和新行的字符。例如正則表達(dá)式 .ar,表示:

任意字符后面跟著一個(gè)字母 a,再后面跟著一個(gè)字母 r。

.ar => The car parked in the garage.

2.2 字符集

字符集也稱為字符類。方括號被用于指定字符集。使用字符集內(nèi)的連字符來指定字符范圍。方括號內(nèi)的字符范圍的順序并不重要

例如正則表達(dá)式 [Tt]he,表示: 大寫 T 小寫 t ,后跟字母 h,再后跟字母 e。

[Tt]he => The car parked in the garage.

然而,字符集中的英文句號表示它字面的含義。正則表達(dá)式 ar[.],表示小寫字母 a,后面跟著一個(gè)字母 r,再后面跟著一個(gè)英文句號 . 字符。

ar[.] => A garage is a good place to park a car.

2.2.1 否定字符集

一般來說插入字符 ^ 表示一個(gè)字符串的開始,但是當(dāng)它在方括號內(nèi)出現(xiàn)時(shí),它會取消字符集。例如正則表達(dá)式 [^c]ar,表示: 除了字母 c 以外的任意字符,后面跟著字符 a,再后面跟著一個(gè)字母 r

[^c]ar => The car parked in the garage.

2.3 重復(fù)

以下元字符 +,*? 用于指定子模式可以出現(xiàn)多少次。這些元字符在不同情況下的作用不同。

2.3.1 星號

該符號 * 表示匹配上一個(gè)匹配規(guī)則的零次或多次。正則表達(dá)式 a* 表示小寫字母 a 可以重復(fù)零次或者多次。但是它如果出現(xiàn)在字符集或者字符類之后,它表示整個(gè)字符集的重復(fù)。

例如正則表達(dá)式 [a-z]*,表示: 一行中可以包含任意數(shù)量的小寫字母。

[a-z]* => The car parked in the garage #21 .

* 符號可以與元符號 . 用在一起,用來匹配任意字符串 .*。該 * 符號可以與空格符 \s 一起使用,用來匹配一串空格字符。

例如正則表達(dá)式 \s*cat\s*,表示:

零個(gè)或多個(gè)空格,后面跟小寫字母 c,再后面跟小寫字母 a,再再后面跟小寫字母 t,后面再跟零個(gè)或多個(gè)空格。

\s*cat\s* => The fat cat sat on the cat.

\s*cat\s* => The fat catcatcat.

2.3.2 加號

該符號 + 匹配上一個(gè)字符的一次或多次。例如正則表達(dá)式 c.+t,表示: 一個(gè)小寫字母 c,后跟任意數(shù)量的字符,后跟小寫字母 t。

c.+t => The fat cat sat on the mat.

c.+t => cat ct

c.+t => ct

注意比較第二個(gè)和第三個(gè)例子。

2.3.3 問號

在正則表達(dá)式中,元字符 ? 用來表示前一個(gè)字符是可選的。該符號匹配前一個(gè)字符的零次或一次

例如正則表達(dá)式 [T]?he,表示:

可選的大寫字母 T,后面跟小寫字母 h,后跟小寫字母 e。

[T]he => The car is parked in the garage.

[T]?he => The car is parked in the garage.

[T]?he => .he ahe TThe

2.4 花括號

在正則表達(dá)式中花括號(也被稱為量詞 ?)用于指定字符或一組字符可以重復(fù)的次數(shù)。例如正則表達(dá)式 [0-9]{2,3},表示: 匹配至少2位數(shù)字但不超過3位(0到9范圍內(nèi)的字符)。

[0-9]{2,3} => The number was 9.9997 but we rounded it off to 10.0.

我們可以省略第二個(gè)數(shù)字。例如正則表達(dá)式 [0-9]{2,},表示:

匹配2個(gè)或更多個(gè)數(shù)字。

如果我們也刪除逗號,則正則表達(dá)式 [0-9]{2},表示:

匹配正好為2位數(shù)的數(shù)字。

[0-9]{2,} => The number was 9.9997 but we rounded it off to 10.0.

[0-9]{2} => The number was 9.9997 but we rounded it off to 10.0.

這里因?yàn)槭侨炙阉?,所以比較起來沒有什么區(qū)別,如果我們關(guān)掉全局搜索,結(jié)果如下:

[0-9]{2,} => The number was 9.9997 but we rounded it off to 10.0.

[0-9]{2} => The number was 9.9997 but we rounded it off to 10.0.

這里再做一個(gè)對比:

[0-9]{2,3} => 2333

[0-9]{2,3} => 23333

這兩個(gè)例子開啟了全局搜索,可以發(fā)現(xiàn),這是優(yōu)先匹配最長的。并且每次匹配都會消耗字符串的,且消耗的是最長的。

2.5 字符組

字符組是一組寫在圓括號內(nèi)的子模式 (...)。正如我們在正則表達(dá)式中討論的那樣,如果我們把一個(gè)量詞放在一個(gè)字符之后,它會重復(fù)前一個(gè)字符。

但是,如果我們把量詞放在一個(gè)字符組之后,它會重復(fù)整個(gè)字符組。

例如正則表達(dá)式 (ab)* 表示匹配零個(gè)或多個(gè)的字符串 "ab"。我們還可以在字符組中使用元字符 |。例如正則表達(dá)式 (c|g|p)ar,表示: 小寫字母 cgp 后面跟字母 a,后跟字母 r

(c|g|p)ar => The car is parked in the garage.

(c|g|p)ar => ar par

2.6 分支結(jié)構(gòu)

在正則表達(dá)式中垂直條 | 用來定義分支結(jié)構(gòu),分支結(jié)構(gòu)就像多個(gè)表達(dá)式之間的條件?,F(xiàn)在你可能認(rèn)為這個(gè)字符集和分支機(jī)構(gòu)的工作方式一樣。

但是字符集和分支結(jié)構(gòu)巨大的區(qū)別是字符集只在字符級別上有作用,然而分支結(jié)構(gòu)在表達(dá)式級別上依然可以使用。

例如正則表達(dá)式 (T|t)he|car,表示: 大寫字母 T 或小寫字母 t,后面跟小寫字母 h,后跟小寫字母 e 或小寫字母 c,后跟小寫字母 a,后跟小寫字母 r

(T|t)he|car => The car is parked in the garage.

2.7 轉(zhuǎn)義特殊字符

正則表達(dá)式中使用反斜杠 \ 來轉(zhuǎn)義下一個(gè)字符。這將允許你使用保留字符來作為匹配字符 { } [ ] / \ + * . $ ^ | ?。在特殊字符前面加 \,就可以使用它來做匹配字符。

例如正則表達(dá)式 . 是用來匹配除了換行符以外的任意字符?,F(xiàn)在要在輸入字符串中匹配 . 字符,正則表達(dá)式 (f|c|m)at\.?,表示:

小寫字母 f、c 或者 m 后跟小寫字母 a,后跟小寫字母 t,后跟可選的 . 字符。

(f|c|m)at\.? => The fat cat sat on the mat.

2.8 定位符

在正則表達(dá)式中,為了檢查匹配符號是否是起始符號或結(jié)尾符號,我們使用定位符。

定位符有兩種類型:

  • 第一種類型是 ^ 檢查匹配字符是否是起始字符;
  • 第二種類型是 $,它檢查匹配字符是否是輸入字符串的最后一個(gè)字符。

2.8.1 插入符號

插入符號 ^ 符號用于檢查匹配字符是否是輸入字符串的第一個(gè)字符。如果我們使用正則表達(dá)式 ^a (如果a是起始符號)匹配字符串 abc,它會匹配到 a。

但是如果我們使用正則表達(dá)式 ^b,它是匹配不到任何東西的,因?yàn)樵谧址?abcb 不是起始字符。

讓我們來看看另一個(gè)正則表達(dá)式 ^(T|t)he,這表示:

大寫字母 T 或小寫字母 t 是輸入字符串的起始符號,后面跟著小寫字母 h,后跟小寫字母 e。

(T|t)he => The car is parked in the garage.

^(T|t)he => The car is parked in the garage.

2.8.2 美元符號

美元 $ 符號用于檢查匹配字符是否是輸入字符串的最后一個(gè)字符。例如正則表達(dá)式 (at\.)$,表示:

小寫字母 a,后跟小寫字母 t,后跟一個(gè) . 字符,且這個(gè)匹配器必須是字符串的結(jié)尾。

(at\.) => The fat cat. sat. on the mat.

(at\.)$ => The fat cat sat on the mat.

3. 簡寫字符集

正則表達(dá)式為常用的字符集和常用的正則表達(dá)式提供了簡寫。簡寫字符集如下:

簡寫 描述
. 匹配除換行符以外的任意字符
\w 匹配所有字母和數(shù)字的字符: [a-zA-Z0-9_]
\W 匹配非字母和數(shù)字的字符: [^\w]
\d 匹配數(shù)字: [0-9]
\D 匹配非數(shù)字: [^\d]
\s 匹配空格符: [\t\n\f\r\p{Z}]
\S 匹配非空格符: [^\s]

4. 斷言

后行斷言和先行斷言有時(shí)候被稱為斷言,它們是特殊類型的 非捕獲組 (用于匹配模式,但不包括在匹配列表中)。當(dāng)我們在一種特定模式之前或者之后有這種模式時(shí),會優(yōu)先使用斷言。

例如我們想獲取輸入字符串 $4.44 and $10.88 中帶有前綴 $ 的所有數(shù)字。我們可以使用這個(gè)正則表達(dá)式 (?<=\$)[0-9\.]*,表示:

獲取包含 . 字符且前綴為 $ 的所有數(shù)字。

以下是正則表達(dá)式中使用的斷言:

符號 描述
?= 正向先行斷言
?! 負(fù)向先行斷言
?<= 正向后行斷言
?<! 負(fù)向后行斷言

4.1 正向先行斷言

正向先行斷言認(rèn)為第一部分的表達(dá)式必須是先行斷言表達(dá)式。返回的匹配結(jié)果僅包含與第一部分表達(dá)式匹配的文本

要在一個(gè)括號內(nèi)定義一個(gè)正向先行斷言,在括號中問號和等號是這樣使用的 (?=...)。先行斷言表達(dá)式寫在括號中的等號后面。

例如正則表達(dá)式 (T|t)he(?=\sfat),表示: 匹配大寫字母 T 或小寫字母 t,后面跟字母 h,后跟字母 e。

在括號中,我們定義了正向先行斷言,它會引導(dǎo)正則表達(dá)式引擎匹配 Thethe 后面跟著 fat。

(T|t)he(?=\sfat) => The fat cat sat on the mat.

(T|t)he(?=\sfat) => The thin cat sat on the mat.

從結(jié)果對比,可以看出,\sfat 是必須要有的,但匹配的結(jié)果不會顯示它。

4.2 負(fù)向先行斷言

當(dāng)我們需要從輸入字符串中獲取不匹配表達(dá)式的內(nèi)容時(shí),使用負(fù)向先行斷言。負(fù)向先行斷言的定義跟我們定義的正向先行斷言一樣,唯一的區(qū)別是不是等號 =,我們使用否定符號 !,例如 (?!...)。

我們來看看下面的正則表達(dá)式 (T|t)he(?!\sfat),表示: 從輸入字符串中獲取全部 The 或者 the 且不匹配 fat 前面加上一個(gè)空格字符。

(T|t)he(?!\sfat) => The fat cat sat on the mat.

這里可以看出,\sfat 是必須不能有的,但匹配的結(jié)果不會顯示它。

4.3 正向后行斷言

正向后行斷言是用于獲取在特定模式之前的所有匹配內(nèi)容。正向后行斷言表示為 (?<=...)。例如正則表達(dá)式 (?<=(T|t)he\s)(fat|mat),表示:

從輸入字符串中獲取在單詞 Thethe 之后的所有 fatmat 單詞。

(?<=(T|t)he\s)(fat|mat) => The fat cat sat on the mat.

從以上結(jié)果可以看到,Thethe 是必須有的,但匹配的結(jié)果不會顯示它。

4.4 負(fù)向后行斷言

負(fù)向后行斷言是用于獲取不在特定模式之前的所有匹配的內(nèi)容。負(fù)向后行斷言表示為 (?<!...)。例如正則表達(dá)式 (?<!(T|t)he\s)(cat),表示:

在輸入字符中獲取所有不在 Thethe 之后的所有單詞 cat。

(?<!(T|t)he\s)(cat) => The cat sat on cat.

從以上結(jié)果可以看到,Thethe 是必須不能有的,但匹配的結(jié)果不會顯示它。

5. 標(biāo)記

標(biāo)記也稱為修飾符,因?yàn)樗鼤薷恼齽t表達(dá)式的輸出。這些標(biāo)志可以以任意順序或組合使用,并且是正則表達(dá)式的一部分。

標(biāo)記 描述
i 不區(qū)分大小寫: 將匹配設(shè)置為不區(qū)分大小寫。
g 全局搜索: 搜索整個(gè)輸入字符串中的所有匹配。
m 多行匹配: 會匹配輸入字符串每一行。

5.1 不區(qū)分大小寫

i 修飾符用于執(zhí)行不區(qū)分大小寫匹配。例如正則表達(dá)式 /The/gi,表示: 大寫字母 T,后跟小寫字母 h,后跟字母 e。

但是在正則匹配結(jié)束時(shí) i 標(biāo)記會告訴正則表達(dá)式引擎忽略這種情況。正如你所看到的,我們還使用了 g 標(biāo)記,因?yàn)槲覀円谡麄€(gè)輸入字符串中搜索匹配。

The => The fat cat sat on the mat.

/The/gi => The fat cat sat on the mat

5.2 全局搜索

g 修飾符用于執(zhí)行全局匹配 (會查找所有匹配,不會在查找到第一個(gè)匹配時(shí)就停止)。

例如正則表達(dá)式 /.(at)/g,表示: 除換行符之外的任意字符,后跟小寫字母 a,后跟小寫字母 t。因?yàn)槲覀冊谡齽t表達(dá)式的末尾使用了 g 標(biāo)記,它會從整個(gè)輸入字符串中找到每個(gè)匹配項(xiàng)。

.(at) => The fat cat sat on the mat.

/.(at)/g => The fat cat sat on the mat.

5.3 多行匹配

m 修飾符被用來執(zhí)行多行的匹配。正如我們前面討論過的 (^, $),使用定位符來檢查匹配字符是輸入字符串開始或者結(jié)束。但是我們希望每一行都使用定位符,所以我們就使用 m 修飾符。

例如正則表達(dá)式 /at(.)?$/gm,表示:

小寫字母 a,后跟小寫字母 t,匹配除了換行符以外任意字符零次或一次。而且因?yàn)?m 標(biāo)記,現(xiàn)在正則表達(dá)式引擎匹配字符串中每一行的末尾。

/.at(.)?$/"=> The fat
cat sat
on the mat.

/.at(.)?$/gm => The fat
cat sat
on the mat.

常用正則表達(dá)式

  • 正整數(shù): ^\d+$
  • 負(fù)整數(shù): ^-\d+$
  • 電話號碼: ^+?[\d\s]{3,}$
  • 電話代碼: ^+?[\d\s]+(?[\d\s]{10,}$
  • 整數(shù): ^-?\d+$
  • 用戶名: ^[\w\d_.]{4,16}$
  • 字母數(shù)字字符: ^[a-zA-Z0-9]*$
  • 帶空格的字母數(shù)字字符: ^[a-zA-Z0-9 ]*$
  • 密碼: ^(?=^.{6,}$)((?=.*[A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z]))^.*$
  • 電子郵件: ^([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})*$
  • IPv4 地址: ^((?:(?: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]?))*$
  • 小寫字母: ^([a-z])*$
  • 大寫字母: ^([A-Z])*$
  • 網(wǎng)址: ^(((http|https|ftp):\/\/)?([[a-zA-Z0-9]\-\.])+(\.)([[a-zA-Z0-9]]){2,4}([[a-zA-Z0-9]\/+=%&_\.~?\-]*))*$
  • VISA 信用卡號碼: ^(4[0-9]{12}(?:[0-9]{3})?)*$
  • 日期 (MM/DD/YYYY): ^(0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])[- /.](19|20)?[0-9]{2}$
  • 日期 (YYYY/MM/DD): ^(19|20)?[0-9]{2}[- /.](0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])$
  • 萬事達(dá)信用卡號碼: ^(5[1-5][0-9]{14})*$

參考資料

[1] ???? 翻譯: 學(xué)習(xí)正則表達(dá)式的簡單方法

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容