參考:正則表達式、正則表達式30分鐘入門教程、正則表達式的使用方法
一、概述
正則表達式(Regular Expression)是一種文本模式,包括普通字符(例如,a 到 z 之間的字母)和特殊字符(稱為“元字符”)。
正則表達式使用單個字符串來描述、匹配一系列匹配某個句法規則的字符串。
正則表達式是繁瑣的,但它是強大的,學會之后的應用會讓你除了提高效率外,會給你帶來絕對的成就感。
二、簡介
除非您以前使用過正則表達式,否則您可能不熟悉一些術語。但是,毫無疑問,您已經使用過不涉及腳本的某些正則表達式概念。
例如,您很可能使用?
和*
通配符來查找硬盤上的文件。?
通配符匹配文件名中的0個或單個字符,而 *
通配符匹配零個或多個字符。像 data?.dat
這樣的模式將查找下列文件:
data1.dat
data2.dat
datax.dat
dataN.dat
使用*
字符代替 ?
字符擴大了找到的文件的數量。data*.dat
匹配下列所有文件:
data.dat
data1.dat
data2.dat
data12.dat
datax.dat
dataXYZ.dat
ps:在OC中的結果,
`data?.dat `匹配
dat.dat
data.dat
datfdat
datagdat
`data*.dat `匹配
dat.dat
data.dat
dataa.dat
dataaa.dat
datfdat
datagdat
datahdat
我主要想說明的是.匹配任意字符
*匹配的是數量上0個或者多個(也就是說,可以沒有,可以有一個,也可以有多個)
?匹配的是數量上0個或者是1個(也就是可以也可以沒有)
盡管這種搜索方法很有用,但它還是有限的。通過理解 * 通配符的工作原理,引入了正則表達式所依賴的概念,但正則表達式功能更強大,而且更加靈活。
正則表達式的使用,可以通過簡單的辦法來實現強大的功能。下面先給出一個簡單的示例:
^[0-9]+abs$
-
^
為匹配輸入字符串的開始位置。 -
[0-9]+
匹配多個數字,[0-9]
匹配單個數字,+
匹配一個或者多個。 -
abc$
匹配字母 abc 并以 abc 結尾,$ 為匹配輸入字符串的結束位置。
示例:
匹配以數字開頭,并以abc結尾的字符串。:
var str = "123abc";
var patt1 = /^[0-9]+abc$/;
document.write(str.match(patt1));
以下標記的文本是獲得的匹配的表達式:
123abc
ps:這只是在文件搜索系統中的正則看,在iOS中則略有不同,所以不要在OC中測試上述正則
為什么要使用正則表達式?
典型的搜索和替換操作要求您提供與預期的搜索結果匹配的確切文本。雖然這種技術對于靜態文本執行簡單的搜索和替換任務已經足夠了,但它缺乏靈活性,若采用這種方法搜索動態文本,即使不是不可能,至少也會變得很困難。
通過正則表達式,可以:
測試字符串內的模式:
例如,可以測試輸入字符串,以查看字符串是否出現電話號碼模式或信用卡號碼模式。這稱為數據驗證。替換文本。
可以使用正則表達式來識別文檔中的特定文本,完全刪除該文本或者用其他文本替換它。基于模式匹配從字符串中提取子字符串。
可以查找文檔內或者輸入域內特定的文本。
例如,您可能需要搜索整個網站,刪除過時的材料,以及替換某些HTML格式標記。在這種情況下,可以使用正則表達式來確定在每個文件中是否出現該材料或該HTML格式標記。此過程將受影響的文件列表縮小到包含需要刪除或更改的材料的那些文件。最后,可以通過正則表達式來搜索和替換標記。
三、正則表達式的語法
下面描述了正則表達式用于匹配字符串中的模式的字符表達式,制定模式匹配多少次的模式運算符和其他匹配限制,最后一個表指定可以包含在正則表達式中的標志通過多行指定搜索行為的模式(也可以使用選項標志來指定這些標志)
表1描述了用于匹配字符串中的字符的字符序列
表格1正則表達式元字符
字符表達 | 描述 |
---|---|
\a | 匹配BELL, \u0007 |
\A | 在輸入開始時匹配。不同于^在\A輸入中的一個新行之后將不匹配。 |
\b, outside of a [Set] | 如果當前位置是字邊界匹配。邊界發生word(\w)和非word(\W)字符之間的轉換處,組合標記被忽略。為了更好的字邊界,請參閱。NSRegularExpressionUseUnicodeWordBoundaries |
\b, within a [Set] | 匹配退格,\u0008。 |
\B | 如果當前位置不是字邊界匹配。 |
\cX | 匹配一個control-X字符 |
\d | 匹配任何字符與Unicode通用類別的Nd(數字,十進制數字) |
\D | 匹配任何不是十進制數字的字符。 |
\e | 匹配ESCAPE,\u001B。 |
\E | 終止\Q ... \E引用的序列。 |
\f | 匹配一個form feed,\u000C。 |
\G | 如果當前位置在上一個匹配結束時匹配。 |
\n | 匹配LINE FEED,\u000A。 |
\N{UNICODE字符名稱} | 匹配named character。 |
\p{UNICODE PROPERTY NAME} | 使用指定的Unicode屬性匹配任何字符。 |
\P{UNICODE PROPERTY NAME} | 匹配任何不具有指定Unicode屬性的字符。 |
\Q | 行情所有后續字符,直到\E。 |
\r | 匹配運送返回,\ u000D。 |
\s | 匹配一個空白字符??崭癖欢x為[\ t \ n \ f \ r \ p {Z}]。 |
\S | 匹配非空白字符。 |
\t | 匹配水平制表符,\u0009。 |
\uhh | 匹配字符與十六進制值hh |
\Uhhhhhhhhh | 匹配字符與十六進制值hhhhhhhhhh。必須提供8位十六進位數字,即使是最大的Unicode代碼點\U0010ffff |
\w | 匹配一個字符 字符是[\ p {L1} \ p {Lu} \ p {Lt} \ p {Lo} \ p {Nd}]。 |
\W | 匹配非字詞。 |
\x{hhhh} | 匹配字符與十六進制值hhhh。可提供1到6個十六進制數字。 |
\x | 匹配字符與兩位十六進制值hh |
\X | 匹配一個化身集群 |
\Z | 如果當前位置在輸入結束處,而在最后一行終止符之前,則匹配,如果存在。 |
\z | 如果當前位置在輸入結束時匹配。 |
\n | 返回參考。匹配任何第n個捕獲組匹配。n必須是模式中的數字≥ 1和≤總數量的捕獲組。 |
\0ooo | 匹配八進制字符 ooo是從一到三個八進制數字。0377是最大允許的八進制角色。領先的零是必需的; 它將八進制常數與反向引用區分開來。 |
[pattern] | 匹配模式中的任何一個字符。 |
. | 匹配任何角色 見并且在字符表達式表4。NSRegularExpressionDotMatchesLineSeparators |
^ | 在一行開始匹配 見并且在字符表達式表4。NSRegularExpressionAnchorsMatchLines\m |
$ | 在一行結束時匹配。見并且在字符表達式表4。NSRegularExpressionAnchorsMatchLines |
引用以下字符。必須引用被視為文字的字符是* ? + [ ( ) { } ^ $ | \ . / |
正則表達式運算符
表2正則表達式運算符
操作 | 描述 | ||
---|---|---|---|
交替 (甲 | 乙)要么匹配甲或乙。 | ||
* | 0或者是更多次數的匹配 | ||
+ | 1或更多次 匹配盡可能多的次數。 | ||
? | 匹配零次或一次 | ||
{n} | 完全匹配n次 | ||
{n,} | 至少匹配n次 匹配盡可能多的次數。 | ||
{n ,m} | n和m之間的匹配。匹配盡可能多的次數,但不能超過m。 | ||
*? | 匹配0或更多次 匹配盡可能少的次數。 | ||
+? | 比賽1次以上 匹配盡可能少的次數。 | ||
?? | 匹配零次或一次。更偏好零。 | ||
{n}? | 完全匹配n次 | ||
{n,}? | 匹配至少n次,但不超過整體模式匹配所需。 | ||
{n,m}? | n和m之間的匹配。匹配次數盡可能少,但不小于n。 | ||
*+ | 匹配0次以上。在第一次遇到時,盡可能多地匹配,即使整體匹配失敗(Possessive Match)也不要重試。 | ||
++ | 匹配一次以上 possessive match | ||
?+ | 匹配零次或一次。possessive match | ||
{n}+ | 完全匹配n次 | ||
{n,}+ | 至少匹配n次possessive match | ||
{n,m}+ | n和m之間的匹配次數,possessive match | ||
(...) | 捕獲括號。匹配圓括號子表達式的輸入范圍在匹配后可用 | ||
(?:...) | 非捕獲括號。對包含的模式進行分組,但不提供匹配文本的捕獲。比捕捉括號更有效率。 | ||
(?>...) | 原子匹配括號。括號子表達式的第一個匹配是唯一一個嘗試; 如果它不會導致整體模式匹配,請在“ (?>” 之前的位置備份搜索匹配 | ||
(?# ... ) | 自由格式的評論(?# comment )。 | ||
(?= ... ) | 先行斷言 如果括號內的圖案在當前輸入位置匹配,但不會提前輸入位置,則為真。 | ||
(?! ... ) | 負面的預言斷言。如果括號中的圖案在當前輸入位置不匹配,則為真。不提高輸入位置。 | ||
(?<= ... ) | 瞻性斷言 如果括號中的模式與當前輸入位置之前的文本匹配,則匹配的最后一個字符就是當前位置之前的輸入字符。不改變輸入位置。由look-behind模式匹配的可能字符串的長度不能是無限制的(否*或+運算符。 | ||
(?<! ... ) | 負面看法斷言。如果括號中的模式與當前輸入位置之前的文本不匹配,則匹配的最后一個字符就是當前位置之前的輸入字符。不改變輸入位置。由look-behind模式匹配的可能字符串的長度不能是無限制的(否*或+運算符。) | ||
(?ismwx-ismwx: ... ) | 標志設置。使用指定的啟用或禁用的標志來評估括號中的表達式。標志在標志選項中定義。 | ||
(?ismwx-ismwx) | 標志設置。更改標志設置。更改適用于設置后的模式部分。例如,(?i)更改為不區分大小寫的匹配。標志在標志選項中定義。 |
模板匹配格式
本類提供了使用模板匹配的技術既可變和不可變的字符串查找和替換的方法。表3描述了語法。
表3模板匹配格式
字符 | 描述 |
---|---|
$n | 捕獲組n的文本將被替換為$ n。n必須>= 0和不大于捕獲組的數量。一個$沒有后面的數字沒有什么特別的意義,并且會以替代文本的形式出現在自己身上$。 |
將以下字符視為文字,抑制任何特殊含義。替換文本中的反斜杠轉義只適用于'$'和'',但可以用于任何其他字符而不會產生不良影響。 |
替換字符串被視為模板,$0被匹配范圍$1的內容,第一個捕獲組的內容替換,等等。除了表示捕獲組數量所需的最大值之外的其他數字將被視為普通字符,$不會跟隨數字。反斜杠將難逃都$和\
標記選項
以下標志控制正則表達式匹配的各個方面。
可以使用(?ismx-ismx)模式選項在模式中指定這些標志值。當使用選項標志初始化時,可以為整個模式指定等效的行為。
NSRegularExpressionNSRegularExpressionOptions
表4 標記選項
flag(pattern) | 描述 |
---|---|
i | 如果設置,匹配將以不區分大小寫的方式進行。 |
X | 如果設置,允許在模式中使用空格和#comments |
s | 如果設置,.模式中的“ ”將匹配輸入文本中的行終止符。默認情況下,它不會。請注意,carriage-return / line-feed pair文本中的內容表現為單行終止符,并將匹配.正則表達式模式中的單個“ ” |
m | 以模式控制“ ^”和“ $” 的行為。默認情況下,這些僅分別匹配輸入文本的開始和結束。如果設置了這個標志,“ ^”和“ $”也將在輸入文本的每一行的開頭和結尾相匹配。 |
w | 控制模式中的行為\b。如果設置,則根據Unicode UAX 29“文本邊界”中發現的詞的定義找到字邊界。默認情況下,通過將字符簡單地分類為“單詞”或“非單詞”來識別字邊界,其近似于傳統的正則表達行為。使用兩個選項獲得的結果在空格和其他非字符字符的運行中可能會有很大差異。 |
性能
NSRegularExpression
實現了非確定性有限自動機匹配引擎。因此,當嘗試執行匹配時,包含多個*或+運算符的復雜正則表達式模式可能會導致較差的性能 -特別是無法匹配給定的輸入。有關更多信息,請參閱“ICU用戶指南”的“性能提示”部分。
四、OC中的Regular表達式NSRegularExpression
NSRegularExpression被設計為不可變的和線程安全的,因此可以一次使用單個實例來匹配多個線程上的操作。但是,在匹配操作的過程中,無論是從另一個線程還是在迭代中使用的塊內,不應該在其上操作它的字符串。
1、創建正在表達式
+ regularExpressionWithPattern:options:error:使用指定的正則表達式模式和選項創建一個NSRegularExpression實例。
- initWithPattern:options:error:
返回具有指定的正則表達式模式和選項的初始化NSRegularExpression實例。
2、獲取正則表達式和選項
pattern
返回正則表達式模式。options
返回創建正則表達式選項時使用的選項。numberOfCaptureGroups
返回正則表達式中捕獲組的數量。
3、使用正則表達式搜索字符串
- numberOfMatchesInString:options:range:
返回字符串指定范圍內正則表達式的匹配數。- enumerateMatchesInString:options:range:usingBlock:
枚舉允許Block處理每個正則表達式匹配的字符串。- matchesInString:options:range:
返回一個數組,其中包含字符串中正則表達式的所有匹配項。
- firstMatchInString:options:range:
返回字符串指定范圍內正則表達式的第一個匹配項。
-
- rangeOfFirstMatchInString:options:range:
返回字符串指定范圍內正則表達式的第一個匹配的范圍。
4、使用正則表達式替換字符串
- replaceMatchesInString:options:range:withTemplate:
使用模板字符串替換可變字符串中的正則表達式匹配。- stringByReplacingMatchesInString:options:range:withTemplate:
返回包含與模板字符串替換的匹配正則表達式的新字符串。
5、在字符串中轉義
+ escapedTemplateForString:
通過根據需要添加反斜杠轉義來返回模板字符串,以保護符合模式元字符的任何字符+ escapedPatternForString:
通過根據需要添加反斜杠轉義來返回字符串,以保護符合模式元字符的任何字符。
6、自定義替換功能
-
- replacementStringForResult:inString:offset:template:
用于為實現自己的替換功能的客戶端執行單個結果的模板替換。
7、常數
NSRegularExpressionOptions
這些常量定義正則表達式選項。
這些常數被 options,和regularExpressionWithPattern:options:error:
initWithPattern:options:error:NSMatchingFlags
由塊匹配進行設置,完成或失敗。
用于該方法
enumerateMatchesInString:options:range:usingBlock:
NSMatchingOptions
匹配選項常量指定表達式匹配方法的報告,完成和匹配規則。
所有使用正則表達式搜索或替換值的方法都使用這些常量。
五、optionals
1、NSMatching 選項
匹配選項常量指定表達式匹配方法的報告,完成和匹配規則。所有使用正則表達式搜索或替換值的方法都使用這些常量。
NSMatchingReportProgress在長時間運行的匹配操作中定期調用Block。此選項對于除此以外的方法沒有影響。請參閱上下文中常量的描述。enumerateMatchesInString:options:range:usingBlock:
enumerateMatchesInString:options:range:usingBlock:NSMatchingReportCompletion
完成任何匹配后,調用Block一次。此選項對于除此以外的方法沒有影響。請參閱上下文中常量的描述。enumerateMatchesInString:options:range:usingBlock:
enumerateMatchesInString:options:range:usingBlock:
NSMatchingAnchored
指定匹配僅限于搜索范圍開始時的匹配。請參閱上下文中常量的描述。NSMatchingWithTransparentBounds
指定匹配可以檢查超出搜索范圍的范圍的字符串的部分,以用于諸如字邊界檢測,前瞻等。如果搜索范圍包含整個字符串,該常量將不起作用。
請參閱上下文中常量的描述。NSMatchingWithoutAnchoringBounds
指定^并且$不會自動匹配搜索范圍的開始和結束,但仍將與整個字符串的開頭和結尾相匹配。如果搜索范圍包含整個字符串,則該常量不起作用。請參閱上下文中常量的描述。 enumerateMatchesInString:options:range:usingBlock:
2、NSRegular表達式選項
NSRegular Expression Case Insensitive
匹配字母在模式中獨立于案例。NSRegular Expression Allow Comments And Whitespace
在模式中忽略空格和#-prefixed注釋。NSRegular Expression Ignore Metacharacters
將整個圖案視為文字字符串。NSRegular Expression Dot Matches Line Separators
允許.匹配任何字符,包括行分隔符。NSRegular Expression Anchors Match Lines
允許^和$匹配行的開始和結束。NSRegular Expression Use Unix Line Separators
僅將\n
視為行分隔符(否則,將使用所有標準行分隔符)。NSRegular Expression Use Unicode Word Boundaries
使用Unicode TR#29來指定字邊界(否則,使用傳統的正則表達式字邊界)。
五、正則表達式的使用
1、謂詞(NSPredicate)創建正則表達式
使用它來判斷用戶輸入的字符串是否為合法的:
// 編寫正則表達式:只能是數字或英文,或兩者都存在
NSString *regex = @"^[a-z0-9A-Z]*$";
// 創建謂詞對象并設定條件的表達式
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
// 判斷的字符串
NSString *str = @"Hello100";
// 對字符串進行判斷
if ([predicate evaluateWithObject:str]) {
NSLog(@"Match");
}
2、NSString實例方法
使用rangeOfString:options:方法可以做到,具體看例子:
NSString *phoneNo = @"13143503442";
NSRange range = [phoneNo rangeOfString:@"^1[3]\\d{9}$" options:NSRegularExpressionSearch];
if (range.location != NSNotFound) {
NSLog(@"%@", [phoneNo substringWithRange:range]);
}
rangeOfString:options:會返回一個NSRange,用來接收匹配的范圍,當匹配不到結果時,將會返回一個NSIntegerMax最大值,也就是NSNotFound,因此我們可以用它來判斷用戶輸入的內容是否符合規則。
3、NSRegularExpression類創建正則表達式
我們可以使用正則來過濾并獲取我們想要的特定部分,實現方法也很簡單,可以用到NSRegularExpression這個類實現:
NSString *url = @"1229436624@qq.com";
NSError *error;
// 創建NSRegularExpression對象并指定正則表達式
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:@"[^@]*\\."
options:0
error:&error];
if (!error) { // 如果沒有錯誤
// 獲取特特定字符串的范圍
NSTextCheckingResult *match = [regex firstMatchInString:url
options:0
range:NSMakeRange(0, [url length])];
if (match) {
// 截獲特定的字符串
NSString *result = [url substringWithRange:match.range];
NSLog(@"%@",result);
}
} else { // 如果有錯誤,則把錯誤打印出來
NSLog(@"error - %@", error);
}
這個例子是從字符串里檢索出以“@”開頭“.”結尾的區間字符串,最后檢索出來的字符串結尾包括“.”,因此此例子最終輸出結果為“qq.”
4、NSRegularExpression類之抓取多個結果
當一個字符串有多個符合特定規則的字符,我們可以分別獲取到符合特定規則的字符:
NSString *regex = @"\\-\\d*\\.";
NSString *str = @"-34023242.-34203020.";
NSError *error;
NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:regex
options:NSRegularExpressionCaseInsensitive
error:&error];
// 對str字符串進行匹配
NSArray *matches = [regular matchesInString:str
options:0
range:NSMakeRange(0, str.length)];
// 遍歷匹配后的每一條記錄
for (NSTextCheckingResult *match in matches) {
NSRange range = [match range];
NSString *mStr = [str substringWithRange:range];
NSLog(@"%@", mStr);
}
從指定字符串中獲取以“-”開頭以“.”結尾的字符,因為可能有多個符合特定規則的字符串,因此我們需要把它們遍歷出來,具體輸出結果如下
017-05-02 16:38:52.309 Juny_regularDemo[1669:190937] -34023242.
2017-05-02 16:38:52.310 Juny_regularDemo[1669:190937] -34203020.
總結:一般來說,判斷用戶輸入的是否合法,只需要方法一就可以了。如果是需要捕獲用戶輸入的特定內容,可以用方法二或者方法三、四,如果可能有多個捕獲結果,那么可以使用方法四,否則使用方法二。