iOS 中:正則表達式患久,又稱正規(guī)表示法椅寺、常規(guī)表示法。(英語:Regular Expression蒋失,在代碼中常簡寫為regex配并、regexp或RE),計算機科學(xué)的一個概念高镐。正則表達式使用單個字符串來描述、匹配一系列符合某個句法規(guī)則畸冲。在很多文本編輯器里嫉髓,正則表達式通常被用來檢索、替換那些符合某個模式的文本邑闲。
先看一下頭文件:
NSRegularExpression:頭文件的枚舉
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, // (查找范圍為整個的話無效)
NSRegularExpressionUseUnicodeWordBoundaries = 1 << 6 // (查找范圍為整個的話無效)
};
這些枚舉是針對表達式的,例如options選擇為:NSRegularExpressionCaseInsensitive苫耸,那么表達式Pattern可以@"Yu"匹配字符串中的yu州邢。
下面2個枚舉貌似都沒什么意義,除了在block方法中,一般情況下,直接給0吧
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é)束
};
此枚舉值只在5.block方法中用到
typedef NS_OPTIONS(NSUInteger, NSMatchingFlags) {
NSMatchingProgress = 1 << 0, //匹配到最長串是被設(shè)置
NSMatchingCompleted = 1 << 1, //全部分配完成后被設(shè)置
NSMatchingHitEnd = 1 << 2, //匹配到設(shè)置范圍的末尾時被設(shè)置
NSMatchingRequiredEnd = 1 << 3, //當(dāng)前匹配到的字符串在匹配范圍的末尾時被設(shè)置
NSMatchingInternalError = 1 << 4 //由于錯誤導(dǎo)致的匹配失敗時被設(shè)置
};
下面是一些方法:
1. 返回所有匹配結(jié)果的集合(適合,從一段字符串中提取我們想要匹配的所有數(shù)據(jù))
* - (NSArray *)matchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
2. 返回正確匹配的個數(shù)(通過等于0,來驗證郵箱,電話什么的,代替NSPredicate)
* - (NSUInteger)numberOfMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
3. 返回第一個匹配的結(jié)果。注意褪子,匹配的結(jié)果保存在 NSTextCheckingResult 類型中
* - (NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
4. 返回第一個正確匹配結(jié)果字符串的NSRange
* - (NSRange)rangeOfFirstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
5. block方法
* - (void)enumerateMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range usingBlock:(void (^)(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop))block;
替換方法:
- (NSString *)stringByReplacingMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)templ;
- (NSUInteger)replaceMatchesInString:(NSMutableString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)templ;
- (NSString *)replacementStringForResult:(NSTextCheckingResult *)result inString:(NSString *)string offset:(NSInteger)offset template:(NSString *)templ;
e.g.
找出并替換
NSString *testStr3 = @"msdfdmmms誰人56dfQs89dfmmmdddmmddfd";
NSString *regex3 = @"誰人";//@"[ms]"
NSRegularExpression *regularE3 = [[NSRegularExpression alloc] initWithPattern:regex3 options:NSRegularExpressionCaseInsensitive error:nil];
NSString *modifiedStr = [regularE3 stringByReplacingMatchesInString:testStr3 options:NSMatchingReportProgress range:NSMakeRange(0, testStr.length) withTemplate:@"&&&"];
NSLog(@"replace:%@",modifiedStr);
基本的NSRegularExpression匹配方法
一個Block遍歷方法量淌,即調(diào)用的時候指定一個Block骗村,進而在執(zhí)行時,會對目標(biāo)string上找到的每個匹配的子串執(zhí)行此Block:
//匹配出來的格式為 +[類名 方法名] 或者 -[類名 方法名]
NSString *regularExpStr = @"[-//|+]\\[.+\\]";
NSRegularExpression *regularExp = [[NSRegularExpression alloc] initWithPattern:regularExpStr options:NSRegularExpressionCaseInsensitive error:nil];
// NSString *testStr = @"2 wgj_avoidCrash 0x0000000106c50534 -[ViewController viewDidLoad] + 212";
NSString *testStr = @"dfadf-[ViewController viewDidLoad]";
__block NSString *resultS = nil;
[regularExp enumerateMatchesInString:testStr options:(NSMatchingReportProgress) range:NSMakeRange(0, testStr.length) usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) {
if (result) {
NSString *resultStr = [testStr substringWithRange:result.range];
resultS = resultStr;
}
}];
NSLog(@"%@",resultS);
此方法為NSRegularExpression最基本的匹配方法呀枢,其遍歷string的每個match胚股,并對每個match進行block中指定的操作,且可在任何執(zhí)行步驟停止裙秋。
返回所有匹配子串 的array
NSString *testStr = @"msdfdmmms56dfQs89dfmmmdddmmddfd";
NSString *regex = @"ms";//@"[ms]"
NSRegularExpression *regularE = [[NSRegularExpression alloc] initWithPattern:regex options:NSRegularExpressionCaseInsensitive error:nil];
NSArray *matches = [regularE matchesInString:testStr options:NSMatchingReportProgress range:NSMakeRange(0, testStr.length)];
NSLog(@"%@",matches);
所有匹配子串?dāng)?shù)目
NSUInteger numOfMatches = [regularE numberOfMatchesInString:testStr options:NSMatchingReportProgress range:NSMakeRange(0, testStr.length)];
NSLog(@"num:%ld",numOfMatches);
//第一個匹配的子串
NSTextCheckingResult *firstMatch = [regularE firstMatchInString:testStr options:NSMatchingReportProgress range:NSMakeRange(0, testStr.length)];
if (firstMatch) {
NSRange range = [firstMatch range];
NSRange firstRange = [firstMatch rangeAtIndex:0];
// NSLog(@"range:%d %d",firstRange,range);
}
//找出第一個匹配的位置和串
NSRange rangeOfFirst = [regularE rangeOfFirstMatchInString:testStr options:NSMatchingReportProgress range:NSMakeRange(0, testStr.length)];
if (!NSEqualRanges(rangeOfFirst, NSMakeRange(NSNotFound, 0))) {
NSString *subStringForFirstMatch = [testStr substringWithRange:rangeOfFirst];
NSLog(@"matchStr:%@",subStringForFirstMatch);
}
//找出并替換
NSString *modifiedStr = [regularE stringByReplacingMatchesInString:testStr options:NSMatchingReportProgress range:NSMakeRange(0, testStr.length) withTemplate:@"&&&"];
NSLog(@"replace:%@",modifiedStr);
返回所有的匹配結(jié)果(正則匹配)
// //returns all the matching results
NSString *testStr2 = @"yuiie7gok8deed78fdsafsd78ree";
NSString *re = @"Yu";
NSRegularExpression *regular2 = [NSRegularExpression regularExpressionWithPattern:re options:(NSRegularExpressionCaseInsensitive) error:nil];
NSArray *matchesArr = [regular2 matchesInString:testStr2
options:0
range:NSMakeRange(0, [testStr2 length])];
for (NSTextCheckingResult *match in matchesArr) {
// NSRange matchRange = [match range];
// NSRange firstHalfRange = [match rangeAtIndex:1];
// NSRange secondHalfRange = [match rangeAtIndex:2];
}
NSString *checkStr = @"thfef我們dfdtel:15236262956fdfd";
NSString *checkRe = @"\\d{3,4}[- ]?\\d{7,8}";//匹配10到12位連續(xù)數(shù)字琅拌,或者帶連字符/空格的固話號,空格和連字符可以省略摘刑。
// NSString *checkRe = @"[0-9]";
//正則匹配
NSRange stringRange = NSMakeRange(0, checkStr.length);
NSError *error;
NSRegularExpression *regexps = [NSRegularExpression regularExpressionWithPattern:checkRe options:0 error:&error];
NSArray *checkResultArr = [regexps matchesInString:checkStr options:0 range:stringRange];
if (checkResultArr) {
for (NSTextCheckingResult *result in checkResultArr) {
NSString *testS = [checkStr substringWithRange:result.range];
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypePhoneNumber | NSTextCheckingTypeLink error:&error];
NSTextCheckingResult *matchesd = [detector firstMatchInString:testS options:0 range:NSMakeRange(0, testS.length)];
if (matchesd) {
NSLog(@"phone:%@",matchesd.phoneNumber);
}
}
}
NSDataDetector繼承于NSRegularExpression进宝,自帶一些過濾功能
NSError *error = nil;
NSString *phhstr = @"www.baidu.comdhfjdfj 15236262956";
NSRange inputRange = NSMakeRange(0, phhstr.length);
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypePhoneNumber | NSTextCheckingTypeLink error:&error];
NSArray *matchesPPP = [detector matchesInString:phhstr options:0 range:inputRange];
for (NSTextCheckingResult *match in matchesPPP) {
//
if ([match resultType] == NSTextCheckingTypePhoneNumber) {
NSRange matchRange = [match range];
NSLog(@"ssss:%@",[phhstr substringWithRange:matchRange]);
}
}
每個單獨的匹配是由NSTextCheckingResult類實例所描述的,其包含整體的匹配range的信息(通過range屬性), 每個捕獲的Group的range(通過rangeAtIndex:方法)枷恕。對于基本的NSRegularExpression對象党晋,這些匹配結(jié)果是 NSTextCheckingTypeRegularExpression類型,NSRegularExpression子類型可以使用其他類型活尊。
所以要獲取某個字符串匹配中的某個group隶校,需要使用 [NSTextCheckingResult rangeAtIndex:groupindex] (0 總是代表整個匹配的range)