正則表達式:是處理字符串的一種表達方式,提供了一種從一組字符串中選擇特定字符串的機制
POSIX規范定義了 UNIX 操作系統支持的功能,POSIX 規范的正則表達式
有兩種:
- BRE (Basic Regular Expression) -- 基本型正則表達式
- ERE (Extended Regular Expression) -- 擴展型正則表達式
這里需要注意一點:正則表達式
和通配符
沒有任何關系,不是包含關系
1、通配符
是Shell
提供的功能
2、正則表達式
只是用來處理字符串
下面我們來看一個常見的正則表達式
,手機號碼的判斷:
^1[3-9](\d{9})$
-
^
:錨點操作符,匹配字符串的開頭,這里緊跟著1
表示以1
開頭的字符串 -
[]
:列表操作符,只匹配中括號中的一個字符 -
-
:范圍操作符,指定的范圍。3-9
表示范圍在3和9之間 -
\d
:代表0-9
之間的數字 -
{}
:間隔運算符,匹配前一個元素N次,這里表示匹配前一個元素9次 -
$
錨點操作符,匹配字符串的結尾
字符匹配
- 我們先來看一些常見的字符
字符 | 描述 |
---|---|
[ABC] |
匹配[...] 中的所有字符,例:[qaz] 匹配字符串"Tiktok Byte Dance"中所有的q a z 字母 |
[^ABC] |
匹配除了[...] 中字符的所有字符,與 [ABC] 相反 |
[A-Z] |
[A-Z] 表示一個區間,匹配所有大寫字母,[a-z] 表示所有小寫字母 |
. |
匹配所有字符,除了\n \r 和null(空字符),相當于[^\n\r] |
\w | 匹配字母、數字、下劃線。等價于[A-Za-z0-9] |
- 重復操作符
字符 | 描述 |
---|---|
* |
匹配前一個元素 0 次 或 多次 |
+ |
匹配前一個元素 1 次 或 多次 |
? |
匹配前一個元素 0 次 或 1次 |
- 間隔操作符
字符 | 描述 |
---|---|
{N} |
匹配前一個元素 N 次,N是一個非負整數 |
{min,} |
匹配前一個元素至少 min 次,min是一個非負整數 |
{min,max} |
匹配前一個元素至少 min 次,至多 max 次;min和max均為非負整數,注意逗號和兩個數之間不能有空格
|
-
列表操作符
[...]
&[^...]
一般操作符在列表操作符
里會失去特殊意義,除了:
字符 | 描述 |
---|---|
] |
結束列表[]]
|
\ |
轉義字符 |
[: |
字符類別操作符開始 |
:] |
字符類別操作符結束 |
- |
范圍操作符,如0-9
|
- 字符類別操作符
字符 | 匹配類型 | 描述 |
---|---|---|
[:alnum:] |
[A-Za-z0-9] | 匹配數字和字母 |
[:alpha:] |
[A-Za-z] | 匹配字母 |
[:blank:] |
[\t] | 匹配空格 和 Tab |
[:cntrl:] |
[\x00-\x1F\x7F] | 匹配控制符 |
[:digit:] |
[0-9] | 匹配數字 |
[:graph:] |
\x21-\x7E | 匹配可視字符 |
[:lower:] |
[a-z] | 匹配小寫字母 |
[:print:] |
[\x20-\x7E] | 匹配可視字符和空格 |
[:punct:] |
][!"#$%&'()*+,./:;<=>?@^_`{}·~-] | 匹配標點符號 |
[:space:] |
[\t\r\n\v\f] | 空白字符 |
[:upper:] |
[A-Z] | 匹配大寫字母字符 |
[:xdigit:] |
[A-Fa-f0-9] | 匹配十六進制字符 |
- 特殊類別操作符
字符 | 匹配類型 | 描述 |
---|---|---|
\w |
[:alnum:] | 匹配數字和字母 |
\d |
[:digit:] | 匹配數字 |
\W |
[^[:alnum:]] | 匹配除了數字和字母 |
\B |
[^[:digit:]] | 匹配除了數字 |
\< |
^ | 匹配字符串的開頭 |
\> |
$ | 匹配字符串的結尾 |
\b |
匹配單詞邊界字符,to\b,但是不匹配tomorrow |
- 錨點操作符
字符 | 描述 |
---|---|
^ |
匹配字符串的開頭,需在開頭 |
$ |
匹配字符串的結尾 或 換行符的前一個位置,需在結尾 |
?? 注意:如果^
在列表操作符中使用,并且在首位,代表取反
操作符的優先級
優先級(由高到低) | 操作符 |
---|---|
歸類相關的括號符號 | [::] |
轉義字符 | \<特殊字符> |
括號表達 | [] |
分組 | () |
單字符重復 |
* + ? {m,n}
|
串聯 | . |
錨點 |
^ $
|
備選 | 豎線(Markdown語法沖突,無法描述) |
貪婪模式、勉強模式、侵占模式
貪婪匹配 | 勉強匹配 | 侵占匹配 | 描述 |
---|---|---|---|
X? |
X?? |
X?+ |
匹配X 零次或一次 |
X* |
X*? |
X*+ |
匹配X 零次或多次 |
X+ |
X+? |
X++ |
匹配X 一次或多次 |
X{n} |
X{n}? |
X{n}+ |
匹配X n次 |
X{n,} |
X{n,}? |
X{n,}+ |
匹配X 至少n次 |
X{n,m} |
X{n,m}? |
X{n,m}+ |
匹配X 至少n次,但不超過m次 |
貪婪模式
例子:GoogleMaps
- 模式:
.*aps
(貪婪模式) 由兩部分組成
1、p1(.*
) :匹配方式為貪婪型
2、p2(aps
)
匹配開始: - 第一輪:
首先,p1會匹配字符串中的所有字符GoogleMaps
,匹配成功;但是p2沒有匹配字符,本輪匹配失敗。 - 第二輪:
減少p1的匹配量,留出最后一個字符,那么此時存在兩個字符串:s1代表GoogleMap
/ s2代表s
。此時s1匹配p1,但是s2不匹配p2,本輪匹配失敗。 - 第三輪:
繼續減少p1的匹配量,留出兩個字符,結果同第二輪一樣。 - 第四輪:
再次減少p1的匹配量,字符串被分割成GoogleM
和aps
兩個部分,此時p1和p2都能匹配。返回匹配成功。
勉強模式
例子:GoogleMaps
- 模式:
.*?aps
(勉強模式) 最小匹配方式,同樣的分為兩部分
1、p1(.*?
) :匹配方式為勉強模式
2、p2(aps
)
匹配開始: - 第一輪:p1由于是0次和任意次,首次匹配0次;則直接用字符串去匹配p2,但是p2無法匹配字符,本輪匹配失敗。
- 第二輪:
增加p1的匹配量,匹配G
;此時存在兩個字符串,s1代表G
/ s2代表oogleMaps
,s1匹配p1,但是s2不匹配p2,本輪匹配失敗。
繼續上述匹配,直到滿足p2
侵占模式
例子:`GoogleMaps
- 模式:
.*+aps
(侵占模式) ,同樣的分為兩部分
1、p1(.*+
) :匹配方式為勉強模式
2、p2(aps
)
匹配開始時讀入所有字符串,和p1匹配成功;但沒有剩余字符串去和p2匹配,匹配失敗。
簡單講,貪婪模式和侵占模式相比,
1、貪婪模式會在只有部分匹配成功的條件下,依次從多到少,減少匹配成功部分的匹配量,將字符留給其他部分去匹配
2、而侵占模式則是占有所有能匹配成功的部分,絕不留給其他部分使用
iOS中正則表達式的應用
NSString *phoneNum = @"1384587921";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^1[3-9]([:digit:]{9})$" options:NSRegularExpressionCaseInsensitive error:&error];
NSTextCheckingResult *result = [regex firstMatchInString:phoneNum options:0 range:NSMakeRange(0, [phoneNum length])];
if (result) {
NSLog(@"匹配成功");
} else {
NSLog(@"匹配失敗");
}
?????? 注意:正則表達式在不同的開發環境中是有所區別的,這一點需要在實際開發中靈活應用,比如:
image.png
在iOS的環境下,
\d
是不識別的。這是因為OC 和 Swift 都要求 轉義文字字符串中的特殊字符(即:在它們前面加上
反斜杠\
)。反斜杠本身就是這樣的特殊字符之一,由于用于創建正則表達式的模式也是字符串,因此會增加復雜性,因為在使用Stingand時需要轉義反斜杠字符NSRegularWxpression。
這也就意味著標準正則表達式\d
,將以\\d
的形式出現在Swift 或 OC 代碼中。這一點大家要注意!
^1[3-9](\\d{9})$
參考文檔:正則表達式 - 語法