正則表達式也用過一段時間了,不同的語言中用起來并不相同,這里姑且做為iOS正則的一個總結(jié)貼。
[TOC]
iOS中的正則表達式
正則語法
1. 基本
我把同類正則符號做了分組列舉,以/作為分隔
| 元字符 | 描述 |
|---|---|
| \ | 轉(zhuǎn)義符 如\\n為\n,單\n為換行符 |
| ^ / $ | 行首與行尾 |
| ? / * / + / {n} / {m,n} | 零次或一次/>=0次/>=1次/n次/m-n次,mn可省略一端限制 |
| ? | 跟在(*,+,?,{n},{n,},{n,m})后面時,為非貪婪模式。如,對于“oooo”,o+得到oooo,o+?得到o |
| x|y | 匹配x或y |
| && | 字符組與運算,有些語言支持,比如&&+[] Java中就支持,但JavaScript不支持。驗證iOS中支持。 |
| [xyz1-9] | 匹配xyz或者1-9數(shù)字其中一個 |
| [^xyz] | 非xyz |
| \b / \B | 單詞/非單詞的邊界,可放前后。如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er” |
| \d / \D | 數(shù)字/非數(shù)字 |
| \s / \S | 不可見/可見字符。\s不可見,等價于[ \f\n\r\t\v] |
| \w / \W | \w包括下劃線的字符,包括字母/數(shù)字/中文/下劃線,不包括emoj。 |
| . | 匹配任何單個字符(注意不包括換行符) |
1.1 &&+[]運算
對于&&+[]運算符,原話是這樣描述的:
有些語言支持,比如&&+[] Java中就支持,但JavaScript不支持。
示例7:匹配英文字母中除去元音字符的字符
[[a-z]&&[^aeiou]] // a-z 且排除掉5個元音字符aeiou
我的驗證,iOS中是支持的。
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"[[a-z ]&&[^acdkn]]+"];
NSLog(@"測試&&:%d", [predicate1 evaluateWithObject:@"better boy"]);
NSLog(@"測試&&:%d", [predicate1 evaluateWithObject:@"better boy run"]);
NSPredicate *predicate11 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"[1234567890&&[^6]]+"];
NSLog(@"測試&&:%d", [predicate11 evaluateWithObject:@"1234567890"]);
NSLog(@"測試&&:%d", [predicate11 evaluateWithObject:@"123457890"]);
/*打印結(jié)果:
2018-10-11 14:15:03.206346+0800 WEEX_TEST[96757:22569846] 測試&&:1
2018-10-11 14:15:03.206425+0800 WEEX_TEST[96757:22569846] 測試&&:0
2018-10-11 14:15:03.206534+0800 WEEX_TEST[96757:22569846] 測試&&:0
2018-10-11 14:15:03.206600+0800 WEEX_TEST[96757:22569846] 測試&&:1
*/
2. 進階
| 元字符 | 描述 |
|---|---|
| \f/\n/\r/\t/\v | 換頁符/換行符/回車符/制表符/垂直制表符 |
| \xn | 十六進制轉(zhuǎn)義值,可表示ASCII編碼。如:“\x41”匹配“A”。 |
| \un | 四個十六進制數(shù)字表示的Unicode字符。如,\u00A9 |
| \n | 標識一個八進制轉(zhuǎn)義值或引用。注:引用優(yōu)先于轉(zhuǎn)義,如前面不足n個表達式,才轉(zhuǎn)義生效。 |
| \num | 對所獲取的匹配的引用。例如,"78aaa",用@"(.)\\1",得到"aa"。????456678aa87aaaas,用@"(\d)(\d)(\w)\3\2\1",得到"78aa87"。注:引用優(yōu)先于轉(zhuǎn)義,如前面不足n個表達式,才轉(zhuǎn)義生效。 |
3. 非獲取匹配
非獲取匹配,匹配pattern但不獲取匹配結(jié)果.
| 元字符 | 描述 |
|---|---|
| ?:pattern | 例如“industr(?:y|ies)”就是一個比“industry|industries”更簡略的表達式。 |
| ?=pattern | 正向肯定預(yù)查. |
| ?<=pattern | 反向肯定預(yù)查. |
| ?!pattern | 正向否定預(yù)查. |
| ?<!pattern | 反向否定預(yù)查. |
其中,包含了4個概念:
- 正向 --> 在查找目標右側(cè)
- 反向 --> 在查找目標左側(cè)
- 肯定 --> 是pattern
- 否定 --> 不是pattern
正常讀起來就是:
- 正向肯定預(yù)查:在目標右側(cè)是pattern
- 反向肯定預(yù)查:在目標左側(cè)是pattern
- 正向否定預(yù)查:在目標右側(cè)不是pattern
- 反向否定預(yù)查:在目標左側(cè)不是pattern
<span id = "jump_find_emoji_code"></span>
來個例子,查找中括號內(nèi)的emoji表情,但不要中括號
//用到了:正向肯定預(yù)查?=與反向肯定預(yù)查?<=
NSString *sourceStr3 = @"我是一個[笑臉],[強],你是一個[自信]";
NSString *pattern = @"(?<=\\[).*?(?=\\])";
NSRegularExpression *regex3 = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:nil];
NSArray<NSTextCheckingResult *> *results3 = [regex3 matchesInString:sourceStr3 options:NSMatchingReportProgress range:NSMakeRange(0, sourceStr3.length)];
for (NSTextCheckingResult *result in results3) {
NSLog(@"中括號內(nèi):%@", [sourceStr3 substringWithRange:result.range]);
}
/*打印結(jié)果:
2018-10-10 16:08:35.145447+0800 WEEX_TEST[15000:20387096] 中括號內(nèi):笑臉
2018-10-10 16:08:35.145550+0800 WEEX_TEST[15000:20387096] 中括號內(nèi):強
2018-10-10 16:08:35.145652+0800 WEEX_TEST[15000:20387096] 中括號內(nèi):自信
*/
分解:
(?<=\\[) //目標左側(cè)是[
.* //查找任意數(shù)量的任意字符,也是我們想查詢的目標
? //非貪婪。如果去掉?,會得到:笑臉],[強],你是一個[自信
(?=\\]) //目標右側(cè)是]
升級一下:如果需求emoji表情為兩個字,如何丟棄一個字的emoji呢?如果有些干擾的或者一半的中括號,如何規(guī)避掉呢?
NSString *sourceStr3 = @"我是一個[笑臉],[[強]],][][[∑??]你是一個[自信]";
NSString *pattern = @"(?<=\\[)([^\\[\\]]{2,}?)(?=\\])";
NSRegularExpression *regex3 = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:nil];
NSArray<NSTextCheckingResult *> *results3 = [regex3 matchesInString:sourceStr3 options:NSMatchingReportProgress range:NSMakeRange(0, sourceStr3.length)];
for (NSTextCheckingResult *result in results3) {
NSLog(@"中括號內(nèi):%@", [sourceStr3 substringWithRange:result.range]);
}
/*打印結(jié)果:
2018-10-10 16:52:30.027836+0800 WEEX_TEST[27737:20549839] 中括號內(nèi):笑臉
2018-10-10 16:52:30.027931+0800 WEEX_TEST[27737:20549839] 中括號內(nèi):∑??
2018-10-10 16:52:30.027984+0800 WEEX_TEST[27737:20549839] 中括號內(nèi):自信
*/
用到了[^]符號,去否定[];用到了{2,},去匹配兩位以上。其實{2,}后面的那個非貪婪?也可以去掉的,因為碰到[]就匹配結(jié)束了,不會出現(xiàn)貪婪∑??]你是一個[自信進來的情況。
iOS中正則的三種表現(xiàn)形式
-
[string rangeOfString: options:]查找字符串范圍,返回第一個匹配成功的range -
NSPredicate謂詞匹配數(shù)組與字符串。 -
NSRegularExpression匹配。
1. [string rangeOfString: options:]
例查找第一個出現(xiàn)的數(shù)字:
NSString *sourceStr2 = @"123元45678秒09分";
NSString *regex2 = @"(?<=“).*(?=”)";
NSRange range2 = [sourceStr2 rangeOfString:regex2 options:NSRegularExpressionSearch];
if (range2.length > 0) {
NSLog(@"%@", [sourceStr2 substringWithRange:range2]);
}
//打?。?23
1.1 出現(xiàn)的option參數(shù)
typedef NS_OPTIONS(NSUInteger, NSStringCompareOptions) {
NSCaseInsensitiveSearch = 1, //不區(qū)分大小寫比較
NSLiteralSearch = 2, //逐字節(jié)比較 區(qū)分大小寫
NSBackwardsSearch = 4, //從字符串末尾開始搜索
NSAnchoredSearch = 8, //搜索限制范圍的字符串
NSNumericSearch = 64, //按照字符串里的數(shù)字為依據(jù),算出順序。例如 Foo2.txt < Foo7.txt < Foo25.txt
NSDiacriticInsensitiveSearch NS_ENUM_AVAILABLE(10_5, 2_0) = 128,//忽略 "-" 符號的比較
NSWidthInsensitiveSearch NS_ENUM_AVAILABLE(10_5, 2_0) = 256,//忽略字符串的長度,比較出結(jié)果
NSForcedOrderingSearch NS_ENUM_AVAILABLE(10_5, 2_0) = 512,//忽略不區(qū)分大小寫比較的選項,并強制返回 NSOrderedAscending 或者 NSOrderedDescending
NSRegularExpressionSearch NS_ENUM_AVAILABLE(10_7, 3_2) = 1024 /*只能應(yīng)用于 rangeOfString:..., stringByReplacingOccurrencesOfString:...和 replaceOccurrencesOfString:... 方法。
使用通用兼容的比較方法,如果設(shè)置此項,可以去掉 NSCaseInsensitiveSearch 和 NSAnchoredSearch*/
};
2. NSPredicate
==NSPredicate下,例子引自: sunny_zl==
其中,只有MATCHES時為正則匹配,這兒也把NSPredicate用法羅列下。
2.1 比較運算符
包括:
1. >=
2. <=
3. >
4. <
5. !=
6. ==
7. BETWEEN {下限,上限} //大于或等于下限
例:
NSNumber *testNumber = @123;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF = 123"];
if ([predicate evaluateWithObject:testNumber]) {
NSLog(@"testString:%@", testNumber);
}
//結(jié)果:testString:123
2.2 邏輯運算符
包括:
1. AND &&
2. OR ||
3. NOT !
例:
NSArray *testArray = @[@1, @2, @3, @4, @5, @6];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF > 2 && SELF < 5"];
NSArray *filterArray = [testArray filteredArrayUsingPredicate:predicate];
NSLog(@"filterArray:%@", filterArray);
//結(jié)果為:(3, 4)
2.3 字符串比較運算符
包括:
1. BEGINSWITH //以指定的字符串開頭
2. ENDSWITH //以指定的字符串結(jié)尾
3. CONTAINS //包含指定的字符串
4. LIKE //是否匹配指定的字符串模板。?代表一個字符和*代表任意多個字符。如:name LIKE '*ac*'中間包含ac;name LIKE '?ac*'匹配第2個位置開始為ac
5. MATCHES //匹配指定的正則表達式
注:字符串比較都是區(qū)分大小寫和重音符號的。
如:café和cafe是不一樣的,Cafe和cafe也是不一樣的。
cd符號:[c]是不區(qū)分大小寫,[d]是不區(qū)分重音符號。如:
name LIKE[cd] 'cafe'
如:
//簡單判斷是否手機號
- (BOOL)checkPhoneNumber:(NSString *)phoneNumber {
NSString *regex = @"^[1][3-8]\\d{9}$";
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
return [pred evaluateWithObject:phoneNumber];
}
2.4 集合運算符
包括:
1. ANY、SOME:集合中任意一個元素滿足條件,就返回YES。
2. ALL:集合中所有元素都滿足條件,才返回YES。
3. NONE:集合中沒有任何元素滿足條件就返回YES。如:NONE person.age < 18
4. IN只有當左邊表達式或值出現(xiàn)在右邊的集合中才會返回YES。
如:
//查找不在filterArray中元素
NSArray *filterArray = @[@"ab", @"abc"];
NSArray *array = @[@"a", @"ab", @"abc", @"abcd"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", filterArray];
NSLog(@"%@", [array filteredArrayUsingPredicate:predicate]);
//輸出:( a, abcd )
2.5 謂詞中使用占位符參數(shù)
包括:
%K:用于動態(tài)傳入屬性名
%@:用于動態(tài)設(shè)置屬性值
$VALUE: 使用動態(tài)改變的屬性值
如:
//定義一個property來存放屬性名,定義一個value來存放值
NSString *property = @"name";
NSString *value = @"Jack";
//該謂詞的作用是如果元素中property屬性含有值value時就取出放入新的數(shù)組內(nèi),這里是name包含Jack
NSPredicate *pred = [NSPredicate predicateWithFormat:@"%K CONTAINS %@", property, value];
NSArray *newArray = [array filteredArrayUsingPredicate:pred];
NSLog(@"newArray:%@", newArray);
//------------- 傳遞VALUE值 -------------
// 創(chuàng)建謂詞,屬性名改為age,要求這個age包含$VALUE字符串,子謂詞傳遞value值
NSPredicate *predTemp = [NSPredicate predicateWithFormat:@"%K > $VALUE", @"age"];
// 指定$VALUE的值為 25
NSPredicate *pred1 = [predTemp predicateWithSubstitutionVariables:@{@"VALUE" : @25}];
NSArray *newArray1 = [array filteredArrayUsingPredicate:pred1];
NSLog(@"newArray1:%@", newArray1);
2.6 基本用法
//字符串內(nèi)查找 查找數(shù)字
NSString *regex = @"\d";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
BOOL match = [predicate evaluateWithObject:sourceString];
//數(shù)字比較 判斷是否100-200間
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF BETWEEN {100, 200}"];
//過濾數(shù)組內(nèi)字符串 在filterArray中
NSArray *filterArray = @[@"ab", @"abc"];
NSArray *array = @[@"a", @"ab", @"abc", @"abcd"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF IN %@", filterArray];
NSArray *newArray = [array filteredArrayUsingPredicate:predicate];
//過濾數(shù)組內(nèi)字典 查找name張姓的
NSArray *array = @[@{@"name" : @"zhangsan", @"age" : @"10"},
@{@"name" : @"lisi", @"age" : @"11"},
@{@"name" : @"wangwu", @"age" : @"12"}];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name CONTAINS[c] 'zhang'"];
NSArray *results = [array filteredArrayUsingPredicate:predicate];
//過濾數(shù)組內(nèi)對象,同數(shù)組內(nèi)字典,不再舉例
//對象的key比較 對象的age大于25
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age > 25"];
3. NSRegularExpression
3.1 查找匹配
1. 查找第一個匹配范圍。
- (NSRange)rangeOfFirstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
2. 查找第一個匹配結(jié)果。
- (nullable NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
3. 查找滿足條件總次數(shù)。
- (NSUInteger)numberOfMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
4. 查找所有匹配結(jié)果。
- (NSArray<NSTextCheckingResult *> *)matchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
5. 查找并通過block遍歷結(jié)果。
- (void)enumerateMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range usingBlock:(void (NS_NOESCAPE ^)(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL *stop))block;
還發(fā)現(xiàn)了一個方法:+ (NSString *)escapedPatternForString:(NSString *)string;,這家伙是用來做什么的呢?它是幫助我們添加轉(zhuǎn)義符的!
如:
NSString *ttt = @"\\d{4,}\n";
NSLog(@"%@", ttt);
NSLog(@"%@", [NSRegularExpression escapedPatternForString:ttt]);
/*打印結(jié)果:
2018-10-10 17:25:16.870223+0800 WEEX_TEST[37135:20678832] \d{4,}
2018-10-10 17:25:16.870438+0800 WEEX_TEST[37135:20678832] \\d\{4,\}
*/
3.2 查找替換
1. 字符串替換,返回一個新串
- (NSString *)stringByReplacingMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)templ;
2. 可變字符串替換,返回操作次數(shù)
- (NSUInteger)replaceMatchesInString:(NSMutableString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)templ;
3. 自定義替換功能(沒搞懂,用了后沒發(fā)現(xiàn)什么作用)
- (NSString *)replacementStringForResult:(NSTextCheckingResult *)result inString:(NSString *)string offset:(NSInteger)offset template:(NSString *)templ;
4. 轉(zhuǎn)換為正則表達式字符串
+ (NSString *)escapedTemplateForString:(NSString *)string;
例子1,查找并替換數(shù)字:
NSString *sourceStr = @"123元45678秒09分";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\d+" options:NSRegularExpressionCaseInsensitive error:nil];
NSArray<NSTextCheckingResult *> *results = [regex matchesInString:sourceStr options:NSMatchingReportProgress range:NSMakeRange(0, sourceStr.length)];
for (NSTextCheckingResult *result in results) {
NSLog(@"%@", [sourceStr substringWithRange:result.range]);
}
NSString *replaced = [regex stringByReplacingMatchesInString:sourceStr options:NSMatchingReportProgress range:NSMakeRange(0, sourceStr.length) withTemplate:@"<<-->>"];
NSLog(@"replaced:%@", replaced);
/*打印結(jié)果:
2018-10-10 17:40:30.122470+0800 WEEX_TEST[41545:20749671] 123
2018-10-10 17:40:30.122601+0800 WEEX_TEST[41545:20749671] 45678
2018-10-10 17:40:30.122712+0800 WEEX_TEST[41545:20749671] 09
2018-10-10 17:40:30.122858+0800 WEEX_TEST[41545:20749671] replaced:<<-->>元<<-->>秒<<-->>分
*/
例子2,可變字符串查找并替換
NSMutableString *sourceStr2 = [@"123元45678秒09分" mutableCopy];
NSInteger replaceNum = [regex replaceMatchesInString:sourceStr2 options:NSMatchingReportProgress range:NSMakeRange(0, sourceStr.length) withTemplate:@"<<-->>"];
NSLog(@"replaceNum:%ld replaced:%@", replaceNum, sourceStr2);
/*打印結(jié)果:
2018-10-10 17:45:56.019120+0800 WEEX_TEST[43137:20772997] replaceNum:3 replaced:<<-->>元<<-->>秒<<-->>分
*/
3.3 出現(xiàn)的option參數(shù)
以下說明引自:roc_lei
NSRegularExpressionOptions:
typedef NS_OPTIONS(NSUInteger, NSRegularExpressionOptions) {
NSRegularExpressionCaseInsensitive = 1 << 0, /*不區(qū)分字母大小寫的模式*/
NSRegularExpressionAllowCommentsAndWhitespace = 1 << 1, /*忽略掉正則表達式中的空格和#號之后的字符*/
NSRegularExpressionIgnoreMetacharacters = 1 << 2, /*將正則表達式整體作為字符串處理*/
NSRegularExpressionDotMatchesLineSeparators = 1 << 3, /*允許.匹配任何字符,包括換行符 */
NSRegularExpressionAnchorsMatchLines = 1 << 4, /*允許^和$符號匹配行的開頭和結(jié)尾*/
NSRegularExpressionUseUnixLineSeparators = 1 << 5, /*設(shè)置\n為唯一的行分隔符*/
NSRegularExpressionUseUnicodeWordBoundaries = 1 << 6 /*使用Unicode TR#29標準作為詞的邊界,否則所有傳統(tǒng)正則表達式的詞邊界都有效*/
};
NSMatchingOptions:
typedef NS_OPTIONS(NSUInteger, NSMatchingOptions) {
NSMatchingReportProgress = 1 << 0, //找到最長的匹配字符串后調(diào)用block回調(diào)
NSMatchingReportCompletion = 1 << 1, //找到任何一個匹配串后都回調(diào)一次block
NSMatchingAnchored = 1 << 2, //從匹配范圍的開始處進行匹配
NSMatchingWithTransparentBounds = 1 << 3, //允許匹配的范圍超出設(shè)置的范圍
NSMatchingWithoutAnchoringBounds = 1 << 4 //禁止^和$自動匹配行還是和結(jié)束
};
NSMatchingFlags:
typedef NS_OPTIONS(NSUInteger, NSMatchingFlags) {
NSMatchingProgress = 1 << 0, //匹配到最長串后被設(shè)置
NSMatchingCompleted = 1 << 1, //全部分配完成后被設(shè)置
NSMatchingHitEnd = 1 << 2, //匹配到設(shè)置范圍的末尾時被設(shè)置
NSMatchingRequiredEnd = 1 << 3, //當前匹配到的字符串在匹配范圍的末尾時被設(shè)置
NSMatchingInternalError = 1 << 4 //由于錯誤導(dǎo)致的匹配失敗時被設(shè)置
};
iOS中正則使用實例
一般使用場景分為兩種,全匹配與輸入框內(nèi)邊輸入邊匹配。
實例這里,只演示簡單正則使用規(guī)則,不做完全嚴格的匹配。
1. 全匹配
1.1 是否有效身份證號
//15或18位身份證:第一位為1-9,中間13或16位數(shù)字,最后一位為0-9xX
BOOL validateIdentityCard(NSString *identityCard){
NSString *regex2 = @"^[1-9](\\d{13}|\\d{16})[0-9xX]$";
NSPredicate *identityCardPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex2];
return [identityCardPredicate evaluateWithObject:identityCard];
}
1.2 是否有效手機號
BOOL validatePhoneNumber(NSString *phone) {
NSString *regex = @"^1[34578]\\d{9}$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
return [predicate evaluateWithObject:phone];
}
1.3 是否有效6-16位密碼
//6-16位密碼,只允許輸入大小寫與數(shù)字,并且大小寫與數(shù)字至少每種一個
BOOL validatePWD(NSString *pwd) {
NSString *regex = @"^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])[a-zA-Z0-9]{6,16}$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
return [predicate evaluateWithObject:pwd];
}
1.4 金額數(shù)字添加逗號分隔符
NSString *sourceText = @"1234567890";
NSString *pattern3 = @"\\B(?=(?:\\d{3})+(?!\\d))";
NSRegularExpression *regex3 = [NSRegularExpression regularExpressionWithPattern:pattern3 options:NSRegularExpressionCaseInsensitive error:nil];
NSArray<NSTextCheckingResult *> *results3 = [regex3 matchesInString:sourceText options:NSMatchingReportProgress range:NSMakeRange(0, sourceText.length)];
NSString *replaced = [regex3 stringByReplacingMatchesInString:sourceText options:NSMatchingReportProgress range:NSMakeRange(0, sourceText.length) withTemplate:@","];
NSLog(@"replaced:%@", replaced);
/*打印結(jié)果:
2018-10-11 10:52:32.896514+0800 WEEX_TEST[38772:22081217] replaced:1,234,567,890
*/
1.5 查找中括號內(nèi)emoji表情
見<a href="#jump_find_emoji_code" target="_self">非獲取匹配中的查找emoji</a>
1.6 限最多8位金額,最多兩位小數(shù),第一位不能為.
//控制8位金額,最多兩位小數(shù),只能輸入數(shù)字與.,第一位不能為.或+-
NSString *toString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSString *stringRegex = @"(([0]|(0[.]\\d{0,2}))|([1-9]\\d{0,7}(([.]\\d{0,2})?)))?";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", stringRegex];
if ([predicate evaluateWithObject:toString]) {
return YES;
}
return NO;
2. 邊輸入邊匹配
邊輸入邊匹配的場景還是挺多的,比如限制輸入框輸入手機號碼,輸入金額,輸入密碼,或輸入身份證號。
它與全匹配不同,需要在輸入過程中,邊輸入邊驗證。當檢測到不匹配時,拒絕用戶輸入,所以用:-textField:shouldChangeCharactersInRange:replacementString:。還要支持回車,退格等。注意:正則檢測的是替換后的string。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
//過濾字符
if ([string isEqualToString:@""] || //按退格可以改變
[string isEqualToString:@"\n"]) { //按回車可以改變
return YES;
}
//因為要匹配的是輸入后字符,所以需要替換操作toString
NSString *toString = [textField.text stringByReplacingCharactersInRange:range withString:string];
//正則檢測
NSString *stringRegex = @"(([0]|(0[.]\\d{0,2}))|([1-9]\\d{0,7}(([.]\\d{0,2})?)))?";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", stringRegex];
if ([predicate evaluateWithObject:toString]) {
return YES;
}
return NO;
}