1萧朝、初級(確定的子字符串)
當NSString中含有多個相同的子字符串腊尚,而又需要查詢所有子字符串的位置時略荡,單純的使用rangeOfString就不好使了庵佣,例如
NSRange range = [@"你可以點擊這里跳轉(zhuǎn),也可以點擊這里跳轉(zhuǎn)" rangeOfString@"跳轉(zhuǎn)"];
只會得到第一個"跳轉(zhuǎn)"的位置撞芍。
解決思路:循環(huán)秧了,從主串第一個字符開始搜索跨扮,每次取出長度為子串長度的字符串序无,如果取出的串與子串的文字一致,存進數(shù)組里衡创,最后帝嗡,數(shù)組里會存放所有的range
代碼如下:
- (NSArray*)rangeOfSubString:(NSString*)subStr inString:(NSString*)string {
? ? ? NSMutableArray *rangeArray = [NSMutableArray array];
? ? ? NSString*string1 = [string stringByAppendingString:subStr];
? ? ? NSString *temp;
? ? ? for(int i =0; i < string.length; i ++) {
? ? ? ? ? ? temp = [string1substringWithRange:NSMakeRange(i, subStr.length)];
? ? ? ? ? ? if ([temp isEqualToString:subStr]) {
? ? ? ? ? ? ? ? ? NSRange range = {i,subStr.length};
? ? ? ? ? ? ? ? ? [rangeArray addObject: [NSValue valueWithRange:range]];
? ? ? ? ? ? }
? ? ? }
? ? ? return rangeArray;?
}
備注:得到返回的數(shù)組后,取出來的元素是NSValue璃氢,需要轉(zhuǎn)換成NSRange使用
NSRange range = [value rangeValue];
2哟玷、高級(正則表達式匹配主串中所有符合條件的子串,并獲得所有子串的文字和位置)
例如一也,我需要獲得主字符串中的網(wǎng)頁鏈接巢寡,需要得到這段鏈接的text(文字)和range(位置),如果主串中只有一個鏈接椰苟,可以這樣獲得
NSString *mainString = @"這里有一個鏈接www.baidu.com";
NSString *regex =@"((http[s]{0,1}|ftp)://[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)|(www.[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)";//正則表達式
NSRange range = [mainString rangeOfString:regex options:NSRegularExpressionSearch];
NSString *subString = [mainString substringWithRange:range];
但是抑月,如果主串中有多個鏈接,這種寫法只會獲得到第一個舆蝴。
2.1谦絮、方法一-原生方法
利用NSRegularExpression處理,直接上代碼
NSString *initialText = @"這里有個鏈接http://www.baidu.com那里也有個鏈接www.sina.com最后還有個鏈接www.taobao.com";
//第一個參數(shù)填正則表達式
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"((http[s]{0,1}|ftp)://[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)|(www.[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)" options:0 error:nil];
NSArray *matches = [regex matchesInString:initialText options:0 range:NSMakeRange(0,initialText.length)];
for(NSTextCheckingResult *result in [matches objectEnumerator]) {
? ? ? NSRangematch Range = [result range];
? ? ? NSLog(@"%@",NSStringFromRange(matchRange));
}
這樣可以獲得所有的range洁仗,通過range再去截取想要的字符串
2.2层皱、方法二-自定義算法
解決思路:循環(huán),搜索到第一個之后赠潦,先把第一個的信息打包成字典存進數(shù)組叫胖,再次搜索,把上次的信息字典取出來她奥,根據(jù)上一個位置信息瓮增,把主串截取為在那之后的串疲陕,記錄新串的頭字符在主串中的位置,在新串中再次搜索钉赁,搜索到的range的location需要加上新串的頭字符在主串中的位置蹄殃,打包信息存進數(shù)組,再次搜索你踩,直到搜索不到信息诅岩。
代碼如下:
- (void)searchAllTextRangeWithInitialArray:(NSMutableArray*)initialArray initialText:(NSString*)initialText regexString:(NSString*)regexString{
? ? ? if (initialArray.count == 0) {//如果此時傳入的array是空
? ? ? ? ? ? NSRange range = [initialText rangeOfString:regexString options:NSRegularExpressionSearch];
? ? ? ? ? ? if (range.location != NSNotFound) {
? ? ? ? ? ? ? ? ? //包裝字典,存進數(shù)組
? ? ? ? ? ? ? ? ? NSMutableDictionary *dict = [NSMutableDictionary dictionary];
? ? ? ? ? ? ? ? ? dict[@"subString"] = [initialText substringWithRange:range];
? ? ? ? ? ? ? ? ? dict[@"subStringRange"] = [NSValue valueWithRange:range];
? ? ? ? ? ? ? ? ? [initialArray addObject:dict];
? ? ? ? ? ? ? ? ? //遞歸調(diào)用
? ? ? ? ? ? ? ? ? [self searchAllTextRangeWithInitialArray:initialArray initialText:initialText regexString:regexString];
? ? ? ? ? ? }else{ ? ??
? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? }
? ? ? }else{//如果數(shù)組中已經(jīng)有值了
? ? ? ? ? ? //1带膜、取數(shù)組中最后一個字典吩谦,記錄后串在原串中的起始位置,把該串及其之前的串去掉生成新串
? ? ? ? ? ? NSMutableDictionary *lastDict = [initialArray lastObject];
? ? ? ? ? ? NSRangelastRange = [lastDict[@"subStringRange"]rangeValue];
? ? ? ? ? ? NSUIntegernewStringBeginLocation = lastRange.location+ lastRange.length;
? ? ? ? ? ? NSString*newString = [initialTextsubstringFromIndex:newStringBeginLocation];
? ? ? ? ? ? //2膝藕、在新串中找符合的子串式廷,如果找到,包裝存進數(shù)組
? ? ? ? ? ? NSRange rangeInNewString = [newString rangeOfString:regexString options:NSRegularExpressionSearch];
? ? ? ? ? ? if(rangeInNewString.location!=NSNotFound) {
? ? ? ? ? ? ? ? ? //包裝字典芭挽,存進數(shù)組
? ? ? ? ? ? ? ? ? NSMutableDictionary*dict = [NSMutableDictionary dictionary];
? ? ? ? ? ? ? ? ?dict[@"subString"] = [newString substringWithRange:rangeInNewString];
? ? ? ? ? ? ? ? ?NSRange rangeIninitialText = NSMakeRange(rangeInNewString.location+newStringBeginLocation, rangeInNewString.length);
? ? ? ? ? ? ? ? ?dict[@"subStringRange"] = [NSValue valueWithRange:rangeIninitialText];
? ? ? ? ? ? ? ? ?[initialArray addObject:dict];
? ? ? ? ? ? ? ? ?//遞歸調(diào)用
? ? ? ? ? ? ? ? ?[self searchAllTextRangeWithInitialArray:initialArray initialText:initialText regexString:regexString];
? ? ? ? ? ?}else{
? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ?}
? ? ? }
}
使用示例:
NSString *initialText = @"這里有個鏈接http://www.baidu.com那里也有個鏈接www.sina.com最后還有個鏈接www.taobao.com";
NSString *regex = @"((http[s]{0,1}|ftp)://[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)|(www.[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)";//正則表達式
NSMutableArray*array = [NSMutableArray array];
[self searchAllTextRangeWithInitialArray:array initialText:initialText regexString:regex];
if(array.count==0) {
? ? ? NSLog(@"查詢失敗");
}else{
? ? ? NSLog(@"查詢成功");
}
//此時滑废,如果有對應的匹配項,數(shù)組中已經(jīng)存好對應的字典了
備注:
1袜爪、array中存的是N個字典蠕趁,每個字典中存了兩個值:子串、子串位置辛馆,結(jié)構(gòu)如下圖
2俺陋、字典中的range是NSValue,需要轉(zhuǎn)換成NSRange使用
(
? ? ? {
? ? ? ? ? ? subString = "http://www.baidu.com";
? ? ? ? ? ? subStringRange = "NSRange: {6, 20}";
? ? ? },
? ? ? {
? ? ? ? ? ? subString = "www.sina.com";
? ? ? ? ? ? subStringRange = "NSRange: {33, 12}";
? ? ? },
? ? ? {
? ? ? ? ? ? subString = "www.taobao.com";
? ? ? ? ? ? subStringRange = "NSRange: {52, 14}";
? ? ? }
)
PS:
1昙篙、上文中的是在網(wǎng)上找到的匹配一段文字中的鏈接的正則表達式腊状,親測好用!如果需要匹配一段文字中的電話號碼苔可、郵箱等缴挖,可以詢問度娘相關(guān)的表達式;
2硕蛹、喜歡可以點個贊哦醇疼!轉(zhuǎn)載請說明出處,謝謝法焰!