轉載自 https://cdoco.com/2017/08/15/learn-regex-zh/
學習正則表達式的簡單方法
Aug 15, 2017 | regex
什麼是正則表達式 ?
正則表達式是一種被用於從文本中檢索符合某些特定模式的文本。
正則表達式是從左到右來匹配一個字符串的。”Regular Expression” 這個詞太長了,我們通常使用它的縮寫 “regex” 或者 “regexp”。正則表達式可以被用來替換字符串中的文本、驗證表單、基於模式匹配從一個字符串中提取字符串等等。
想象一下,您正在編寫應用程序,並且您希望在用戶選擇用戶名時設置規則。我們希望用戶名可以包含字母,數字,下劃線和連字符。爲了讓它看起來不醜,我們還想限制用戶名中的字符數量。我們可以使用以下正則表達式來驗證用戶名:
上面這個正則表達式可以匹配 john_doe
,jo-hn\_doe
和 john12\_as
。但是它不能匹配 Jo
,因爲該字符串裏面包含了大寫字符,並且它太短了。
目錄
1. 基本匹配
正則表達式只是我們用於在文本中檢索字母和數字的模式。例如正則表達式 cat
,表示: 字母 c
後面跟着一個字母 a
,再後面跟着一個字母 t
。
"cat" => The cat sat on the mat
正則表達式 123
會匹配字符串 “123”。通過將正則表達式中的每個字符逐個與要匹配的字符串中的每個字符進行比較,來完成正則匹配。正則表達式通常區分大小寫,因此正則表達式 Cat
與字符串 “cat” 不匹配。
"Cat" => The cat sat on the Cat
2. 元字符
元字符是正則表達式的基本組成元素。元字符在這裏跟它通常表達的意思不一樣,而是以某種特殊的含義去解釋。有些元字符寫在方括號內的時候有特殊含義。
元字符如下:
元字符 | 描述 |
---|---|
. | 匹配除換行符以外的任意字符。 |
[ ] | 字符類,匹配方括號中包含的任意字符。 |
[^ ] | 否定字符類。匹配方括號中不包含的任意字符 |
* | 匹配前面的子表達式零次或多次 |
+ | 匹配前面的子表達式一次或多次 |
? | 匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。 |
{n,m} | 花括號,匹配前面字符至少 n 次,但是不超過 m 次。 |
(xyz) | 字符組,按照確切的順序匹配字符xyz。 |
| | 分支結構,匹配符號之前的字符或後面的字符。 |
\ | 轉義符,它可以還原元字符原來的含義,允許你匹配保留字符 [ ] ( ) { } . * + ? ^ $ \ | |
^ | 匹配行的開始 |
$ | 匹配行的結束 |
2.1 英文句號
英文句號 .
是元字符的最簡單的例子。元字符 .
可以匹配任意單個字符。它不會匹配換行符和新行的字符。例如正則表達式 .ar
,表示: 任意字符後面跟着一個字母 a
,再後面跟着一個字母 r
。
".ar" => The car parked in the garage.
2.2 字符集
字符集也稱爲字符類。方括號被用於指定字符集。使用字符集內的連字符來指定字符範圍。方括號內的字符範圍的順序並不重要。例如正則表達式 [Tt]he
,表示: 大寫 T
或小寫 t
,後跟字母 h
,再後跟字母 e
。
"[Tt]he" => The car parked in the garage.
然而,字符集中的英文句號表示它字面的含義。正則表達式 ar[.]
,表示小寫字母 a
,後面跟着一個字母 r
,再後面跟着一個英文句號 .
字符。
"ar[.]" => A garage is a good place to park a car.
2.2.1 否定字符集
一般來說插入字符 ^
表示一個字符串的開始,但是當它在方括號內出現時,它會取消字符集。例如正則表達式 [^c]ar
,表示: 除了字母 c
以外的任意字符,後面跟着字符 a
,再後面跟着一個字母 r
。
"[^c]ar" => The car parked in the garage.
2.3 重複
以下元字符 +
,*
或 ?
用於指定子模式可以出現多少次。這些元字符在不同情況下的作用不同。
2.3.1 星號
該符號 *
表示匹配上一個匹配規則的零次或多次。正則表達式 a*
表示小寫字母 a
可以重複零次或者多次。但是它如果出現在字符集或者字符類之後,它表示整個字符集的重複。例如正則表達式 [a-z]*
,表示: 一行中可以包含任意數量的小寫字母。
"[a-z]*" => The car parked in the garage #21.
該 *
符號可以與元符號 .
用在一起,用來匹配任意字符串 .*
。該 *
符號可以與空格符 \s
一起使用,用來匹配一串空格字符。例如正則表達式 \s*cat\s*
,表示: 零個或多個空格,後面跟小寫字母 c
,再後面跟小寫字母 a
,再再後面跟小寫字母 t
,後面再跟零個或多個空格。
"\s*cat\s*" => The fat cat sat on the cat.
2.3.2 加號
該符號 +
匹配上一個字符的一次或多次。例如正則表達式 c.+t
,表示: 一個小寫字母 c
,後跟任意數量的字符,後跟小寫字母 t
。
"c.+t" => The fat cat sat on the mat.
2.3.3 問號
在正則表達式中,元字符 ?
用來表示前一個字符是可選的。該符號匹配前一個字符的零次或一次。例如正則表達式 [T]?he
,表示: 可選的大寫字母 T
,後面跟小寫字母 h
,後跟小寫字母 e
。
"[T]he" => The car is parked in the garage.
"[T]?he" => The car is parked in the garage.
2.4 花括號
在正則表達式中花括號(也被稱爲量詞 ?)用於指定字符或一組字符可以重複的次數。例如正則表達式 [0-9]{2,3}
,表示: 匹配至少2位數字但不超過3位(0到9範圍內的字符)。
"[0-9]{2,3}" => The number was 9.9997 but we rounded it off to 10.0.
我們可以省略第二個數字。例如正則表達式 [0-9]{2,}
,表示: 匹配2個或更多個數字。如果我們也刪除逗號,則正則表達式 [0-9]{2}
,表示: 匹配正好爲2位數的數字。
"[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.
2.5 字符組
字符組是一組寫在圓括號內的子模式 (...)
。正如我們在正則表達式中討論的那樣,如果我們把一個量詞放在一個字符之後,它會重複前一個字符。但是,如果我們把量詞放在一個字符組之後,它會重複整個字符組。例如正則表達式 (ab)*
表示匹配零個或多個的字符串 “ab”。我們還可以在字符組中使用元字符 |
。例如正則表達式 (c|g|p)ar
,表示: 小寫字母 c
、g
或 p
後面跟字母 a
,後跟字母 r
。
"(c|g|p)ar" => The car is parked in the garage.
2.6 分支結構
在正則表達式中垂直條 |
用來定義分支結構,分支結構就像多個表達式之間的條件。現在你可能認爲這個字符集和分支機構的工作方式一樣。但是字符集和分支結構巨大的區別是字符集只在字符級別上有作用,然而分支結構在表達式級別上依然可以使用。例如正則表達式 (T|t)he|car
,表示: 大寫字母 T
或小寫字母 t
,後面跟小寫字母 h
,後跟小寫字母 e
或小寫字母 c
,後跟小寫字母 a
,後跟小寫字母 r
。
"(T|t)he|car" => The car is parked in the garage.
2.7 轉義特殊字符
正則表達式中使用反斜槓 \
來轉義下一個字符。這將允許你使用保留字符來作爲匹配字符 { } [ ] / \ + * . $ ^ | ?
。在特殊字符前面加 \
,就可以使用它來做匹配字符。例如正則表達式 .
是用來匹配除了換行符以外的任意字符。現在要在輸入字符串中匹配 .
字符,正則表達式 (f|c|m)at\.?
,表示: 小寫字母 f
、c
或者 m
後跟小寫字母 a
,後跟小寫字母 t
,後跟可選的 .
字符。
"(f|c|m)at\.?" => The fat cat sat on the mat.
2.8 定位符
在正則表達式中,爲了檢查匹配符號是否是起始符號或結尾符號,我們使用定位符。定位符有兩種類型: 第一種類型是 ^
檢查匹配字符是否是起始字符,第二種類型是 $
,它檢查匹配字符是否是輸入字符串的最後一個字符。
2.8.1 插入符號
插入符號 ^
符號用於檢查匹配字符是否是輸入字符串的第一個字符。如果我們使用正則表達式 ^a
(如果a是起始符號)匹配字符串 abc
,它會匹配到 a
。但是如果我們使用正則表達式 b
,它是匹配不到任何東西的,因爲在字符串 abc
中 “b” 不是起始字符。讓我們來看看另一個正則表達式 ^(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 美元符號
美元 $
符號用於檢查匹配字符是否是輸入字符串的最後一個字符。例如正則表達式 (at\.)$
,表示: 小寫字母 a
,後跟小寫字母 t
,後跟一個 .
字符,且這個匹配器必須是字符串的結尾。
"(at\.)" => The fat cat. sat. on the mat.
"(at\.)$" => The fat cat sat on the mat.
3. 簡寫字符集
正則表達式爲常用的字符集和常用的正則表達式提供了簡寫。簡寫字符集如下:
簡寫 | 描述 |
---|---|
. | 匹配除換行符以外的任意字符 |
\w | 匹配所有字母和數字的字符: [a-zA-Z0-9_] |
\W | 匹配非字母和數字的字符: [^\w] |
\d | 匹配數字: [0-9] |
\D | 匹配非數字: [^\d] |
\s | 匹配空格符: [\t\n\f\r\p{Z}] |
\S | 匹配非空格符: [^\s] |
4. 斷言
後行斷言和先行斷言有時候被稱爲斷言,它們是特殊類型的 非捕獲組 (用於匹配模式,但不包括在匹配列表中)。當我們在一種特定模式之前或者之後有這種模式時,會優先使用斷言。例如我們想獲取輸入字符串 $4.44 and $10.88
中 $
字符之前的所有數字。我們可以使用這個正則表達式 (?<=\$)[0-9\.]*
,表示: 獲取 $
字符之前的所有的數字包含 .
字符。以下是正則表達式中使用的斷言:
符號 | 描述 |
---|---|
?= | 正向先行斷言 |
?! | 負向先行斷言 |
?<= | 正向後行斷言 |
?<! | 負向後行斷言 |
4.1 正向先行斷言
正向先行斷言認爲第一部分的表達式必須是先行斷言表達式。返回的匹配結果僅包含與第一部分表達式匹配的文本。要在一個括號內定義一個正向先行斷言,在括號中問號和等號是這樣使用的 (?=...)
。先行斷言表達式寫在括號中的等號後面。例如正則表達式 (T|t)he(?=\sfat)
,表示: 匹配大寫字母 T
或小寫字母 t
,後面跟字母 h
,後跟字母 e
。在括號中,我們定義了正向先行斷言,它會引導正則表達式引擎匹配 The
或 the
後面跟着 fat
。
"(T|t)he(?=\sfat)" => The fat cat sat on the mat.
4.2 負向先行斷言
當我們需要從輸入字符串中獲取不匹配表達式的內容時,使用負向先行斷言。負向先行斷言的定義跟我們定義的正向先行斷言一樣,唯一的區別是不是等號 =
,我們使用否定符號 !
,例如 (?!...)
。我們來看看下面的正則表達式 (T|t)he(?!\sfat)
,表示: 從輸入字符串中獲取全部 The
或者 the
且不匹配 fat
前面加上一個空格字符。
"(T|t)he(?!\sfat)" => The fat cat sat on the mat.
4.3 正向後行斷言
正向後行斷言是用於獲取在特定模式之前的所有匹配內容。正向後行斷言表示爲 (?<=...)
。例如正則表達式 (?<=(T|t)he\s)(fat|mat)
,表示: 從輸入字符串中獲取在單詞 The
或 the
之後的所有 fat
和 mat
單詞。
"(?<=(t|t)he\s)(fat|mat)" ==""> The fat cat sat on the mat.
4.4 負向後行斷言
負向後行斷言是用於獲取不在特定模式之前的所有匹配的內容。負向後行斷言表示爲 (?<!...)
。例如正則表達式 (?<!(T|t)he\s)(cat)
,表示: 在輸入字符中獲取所有不在 The
或 the
之後的所有單詞 cat
。
"(?<!(T|t)he\s)(cat)" => The cat sat on cat.
5. 標記
標記也稱爲修飾符,因爲它會修改正則表達式的輸出。這些標誌可以以任意順序或組合使用,並且是正則表達式的一部分。
標記 | 描述 |
---|---|
i | 不區分大小寫: 將匹配設置爲不區分大小寫。 |
g | 全局搜索: 搜索整個輸入字符串中的所有匹配。 |
m | 多行匹配: 會匹配輸入字符串每一行。 |
5.1 不區分大小寫
i
修飾符用於執行不區分大小寫匹配。例如正則表達式 /The/gi
,表示: 大寫字母 T
,後跟小寫字母 h
,後跟字母 e
。但是在正則匹配結束時 i
標記會告訴正則表達式引擎忽略這種情況。正如你所看到的,我們還使用了 g
標記,因爲我們要在整個輸入字符串中搜索匹配。
"The" => The fat cat sat on the mat.
"/The/gi" => The fat cat sat on the mat.
5.2 全局搜索
g
修飾符用於執行全局匹配 (會查找所有匹配,不會在查找到第一個匹配時就停止)。例如正則表達式 /.(at)/g
,表示: 除換行符之外的任意字符,後跟小寫字母 a
,後跟小寫字母 t
。因爲我們在正則表達式的末尾使用了 g
標記,它會從整個輸入字符串中找到每個匹配項。
".(at)" => The fat cat sat on the mat.
"/.(at)/g" => The fat cat sat on the mat.
5.3 多行匹配
m
修飾符被用來執行多行的匹配。正如我們前面討論過的 (^, $)
,使用定位符來檢查匹配字符是輸入字符串開始或者結束。但是我們希望每一行都使用定位符,所以我們就使用 m
修飾符。例如正則表達式 /at(.)?$/gm
,表示: 小寫字母 a
,後跟小寫字母 t
,匹配除了換行符以外任意字符零次或一次。而且因爲 m
標記,現在正則表達式引擎匹配字符串中每一行的末尾。
"/.at(.)?$/" => The fat cat sat on the mat.
"/.at(.)?$/gm" => The fat cat sat on the mat.
福利
- 正整數:
^\d+$
- 負整數:
^-\d+$
- 電話號碼:
^+?[\d\s]{3,}$
- 電話代碼:
^+?[\d\s]+(?[\d\s]{10,}$
- 整數:
^-?\d+$
- 用戶名:
^[\w\d_.]{4,16}$
- 字母數字字符:
^[a-zA-Z0-9]*$
- 帶空格的字母數字字符:
^[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})*$
- 小寫字母:
^([a-z])*$
- 大寫字母:
^([A-Z])*$
- VISA 信用卡號碼:
^(4[0-9]{12}(?:[0-9]{3})?)*$
- 萬事達信用卡號碼:
^(5[1-5][0-9]{14})*$