iOS深思篇 | 正則表示式
一. 背景
1.1 簡介
關於正則表示式,相信大家並不陌生,可能平時只是貼上下相關程式碼,並不瞭解裡面所寫匹配規則。這篇文章我們將介紹iOS相關正則表示式基本語法和一些例項,希望看完此文大家能有所收穫;
1.2 工具
線上匹配工具
安裝包
圖形化展示工具
eg:
庫
二. 認識正則表示式
2.1 概念
正則表示式(又稱規則表示式),英語為Regular Expression
regex
、regexp
或RE
。它使用單個字串來描述,匹配一系列符合某個句法規則的字串。
使用場景:
- 用來批量提取或替換有規律的字串;
- 在高階文字編輯器中使用;
- 在各類辦公軟體(office等)中使用;
- 檢測使用者的輸入是否合法;
- 在各種開發語言中使用;(C#,java,JS,PHP等)
- 網路爬蟲;
- 批量文字處理等;
eg:
2.2 初識篇
正則表示式是由普通字元和特殊字元(也叫元字元或限定符)組成的文字模板,為用來描述或匹配符合某個句法規則的字串。在許多軟體中都得到廣泛的應用,當然針對不同的命令及環境,對正則表示式的支援程度也不盡相同,這裡參考正則表示式 - 應用領域
"/"是JS中經常用來分隔一個正則的開始與結尾的字元,其他語言中不用做此區分;
比如:
/* JS */
/abc/ //精確匹配abc(有/符號)
/* 其他語言 */
abc //精確匹配abc(無/符號)
複製程式碼
很多人剛開始無從下手可能是因為不清楚如何"斷句",這樣也就抓不住重點,感覺像聽天書了。?我們可以這樣拆開來看,把正則表示式看成是普通字元和其他字元的集合。普通字元包括所有大寫和小寫字母、所有數字、所有標點符號和一些其他符號(PS:就是平時看得懂的符號?);其他字元包括了常說的元字元、運算子、限定符、特殊字元等等;
下面是一個匹配以數字開頭,並以 abc 結尾的字串;
^ [0-9] + abc $
定位符 字符集 限定符 普通字元 限定符
複製程式碼
各種字元的詳細解釋可參照正則表示式 - 語法。之後稍微瞭解一點語法,就可以嘗試自己斷句了,為了少走彎路,建議參照圖形化展示工具regulex對比理解。
2.3 語法篇
語法篇主要參照learn-regex的劃分;大家可以參照作者的線上練習進行學習,下面?僅附上主要元字元對照表。
2.3.1 元字元
正則表示式主要依賴於元字元. 元字元不代表他們本身的字面意思,他們都有特殊的含義. 一些元字元寫在方括號中的時候有一些特殊的意思. 以下是一些元字元的介紹:
元字元 | 描述 |
---|---|
. | 句號匹配任意單個字元除了換行符. |
[ ] | 字元種類. 匹配方括號內的任意字元. |
[^ ] | 否定的字元種類. 匹配除了方括號裡的任意字元 |
* | 匹配>=0個重複的在*號之前的字元. |
+ | 匹配>=1個重複的+號前的字元. |
? | 標記?之前的字元為可選. |
{n,m} | 匹配num個大括號之前的字元 (n <= num <= m). |
(xyz) | 字符集,匹配與 xyz 完全相等的字串. |
| | 或運算子,匹配符號前或後的字元. |
\ | 轉義字元,用於匹配一些保留的字元 [ ] ( ) { } . * + ? ^ $ \ |
|
^ | 從開始行開始匹配. |
$ | 從末端開始匹配. |
2.3.2 簡寫字符集
正則表示式提供一些常用的字符集簡寫. 如下:
簡寫 | 描述 |
---|---|
. | 除換行符外的所有字元 |
\w | 匹配所有字母數字,等同於 [a-zA-Z0-9_]
|
\W | 匹配所有非字母數字,即符號,等同於: [^\w]
|
\d | 匹配數字: [0-9]
|
\D | 匹配非數字: [^\d]
|
\s | 匹配所有空格字元,等同於: [\t\n\f\r\p{Z}]
|
\S | 匹配所有非空格字元: [^\s]
|
\f | 匹配一個換頁符 |
\n | 匹配一個換行符 |
\r | 匹配一個回車符 |
\t | 匹配一個製表符 |
\v | 匹配一個垂直製表符 |
\p | 匹配 CR/LF (等同於 \r\n ),用來匹配 DOS 行終止符 |
2.3.3 零寬度斷言(前後預查)
先行斷言和後發斷言都屬於非捕獲簇(不捕獲文字 ,也不針對組合計進行計數). 先行斷言用於判斷所匹配的格式是否在另一個確定的格式之前,匹配結果不包含該確定格式(僅作為約束).
例如,我們想要獲得所有跟在 $
符號後的數字,我們可以使用正後發斷言 (?<=\$)[0-9\.]*
.
這個表示式匹配 $
開頭,之後跟著 0,1,2,3,4,5,6,7,8,9,.
這些字元可以出現大於等於 0 次.
零寬度斷言如下:
符號 | 描述 |
---|---|
?= | 正先行斷言-存在 |
?! | 負先行斷言-排除 |
?<= | 正後發斷言-存在 |
?<! | 負後發斷言-排除 |
2.3.4 標誌
標誌也叫模式修正符,因為它可以用來修改表示式的搜尋結果. 這些標誌可以任意的組合使用,它也是整個正則表示式的一部分.
標誌 | 描述 |
---|---|
i | 忽略大小寫. |
g | 全域性搜尋. |
m | 多行的: 錨點元字元 ^ $ 工作範圍在每行的起始. |
2.3.5 優先順序
在這些運算子同時出現時,按照下面的優先順序進行操作。
優先順序 | 符號 |
---|---|
最高 | \ |
高 | ( )、(?: )、(?= )、[ ] |
中 | *、+、?、{n}、{n,}、{n,m} |
低 | ^、$、中介字元 |
最低 | | |
2.4 進階篇
2.4.1 貪婪匹配與惰性匹配
正則表示式預設採用貪婪匹配模式,在該模式下意味著會匹配儘可能長的子串。我們可以使用 ? 將貪婪匹配模式轉化為惰性匹配模式。 貪婪模式
(.*nt)
=>People want to try something different
.
惰性模式
(.*?nt)
=>People want
to try something different.
常見的惰性限定符:
符號 | 說明 |
---|---|
*? | 重複任意次,但儘可能少重複 |
+? | 重複1次或更多次,但儘可能少重複 |
?? | 重複0次或1次,但儘可能少重複 |
{n,m}? | 重複n到m次,但儘可能少重複 |
{n,}? | 重複n次以上,但儘可能少重複 |
三. iOS中的應用
3.1 謂詞(NSPredicate)
NSString *regex = @"^[0-9]+$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
NSString *str = @"1314";
if ([predicate evaluateWithObject:str]) {
NSLog(@"Condition Matched");
}
複製程式碼
3.2 NSString
NSString *searchText = @"targetString";
NSRange range = [searchText rangeOfString:@"^[0-9]+$" options:NSRegularExpressionSearch];
if (range.location != NSNotFound) {
NSLog(@"target range :%@",[searchText substringWithRange:range]);
}
複製程式碼
3.3 NSRegularExpression
/*
typedef NS_OPTIONS(NSUInteger,NSRegularExpressionOptions) {
NSRegularExpressionCaseInsensitive = 1 << 0,//不區分字母大小寫的模式
NSRegularExpressionAllowCommentsAndWhitespace = 1 << 1,//忽略掉正則表示式中的空格和#號之後的字元
NSRegularExpressionIgnoreMetacharacters = 1 << 2,//將正則表示式整體作為字串處理
NSRegularExpressionDotMatchesLineSeparators = 1 << 3,//允許.匹配任何字元,包括換行符
NSRegularExpressionAnchorsMatchLines = 1 << 4,//允許^和$符號匹配行的開頭和結尾
NSRegularExpressionUseUnixLineSeparators = 1 << 5,//設定\n為唯一的行分隔符,否則所有的都有效。
NSRegularExpressionUseUnicodeWordBoundaries = 1 << 6 //使用Unicode TR#29標準作為詞的邊界,否則所有傳統正則表示式的詞邊界都有效
};
*/
NSString *searchText = @"what do you want to match string";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^[0-9]+$" options:NSRegularExpressionCaseInsensitive error:&error];
//僅取出第一條匹配記錄
NSTextCheckingResult *firstResult = [regex firstMatchInString:searchText options:0 range:NSMakeRange(0,[searchText length])];
if (firstResult) {
NSLog(@"firstResult:%@",[searchText substringWithRange:firstResult.range]);
}
//遍歷所有匹配記錄
NSArray *matches = [regex matchesInString:searchText
options:0
range:NSMakeRange(0,searchText.length)];
for (NSTextCheckingResult *match in matches) {
NSRange range = [match range];
NSString *mStr = [searchText substringWithRange:range];
NSLog(@"AllResult:%@",mStr);
}
複製程式碼
學習:
blog
- learn-regex
- 最全的常用正則表示式大全——包括校驗數字、字元、一些特殊的需求等等 - zxin - 部落格園
- NSRegularExpression Tutorial and Cheat Sheet
- 正則表示式-維基百科
- The Stack Overflow Regular Expressions FAQ
- 正則表示式NSRegularExpression · pro648/tips Wiki · GitHub