1、初級(確定的子字符串)
當NSString中含有多個相同的子字符串,而又需要查詢所有子字符串的位置時,單純的使用rangeOfString就不好使了,例如
NSRange range = [@"你可以點擊這里跳轉,也可以點擊這里跳轉" rangeOfString@"跳轉"];
只會得到第一個"跳轉"的位置。
解決思路:循環,從主串第一個字符開始搜索,每次取出長度為子串長度的字符串,如果取出的串與子串的文字一致,存進數組里,最后,數組里會存放所有的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;?
}
備注:得到返回的數組后,取出來的元素是NSValue,需要轉換成NSRange使用
NSRange range = [value rangeValue];
2、高級(正則表達式匹配主串中所有符合條件的子串,并獲得所有子串的文字和位置)
例如,我需要獲得主字符串中的網頁鏈接,需要得到這段鏈接的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";
//第一個參數填正則表達式
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、方法二-自定義算法
解決思路:循環,搜索到第一個之后,先把第一個的信息打包成字典存進數組,再次搜索,把上次的信息字典取出來,根據上一個位置信息,把主串截取為在那之后的串,記錄新串的頭字符在主串中的位置,在新串中再次搜索,搜索到的range的location需要加上新串的頭字符在主串中的位置,打包信息存進數組,再次搜索,直到搜索不到信息。
代碼如下:
- (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) {
? ? ? ? ? ? ? ? ? //包裝字典,存進數組
? ? ? ? ? ? ? ? ? NSMutableDictionary *dict = [NSMutableDictionary dictionary];
? ? ? ? ? ? ? ? ? dict[@"subString"] = [initialText substringWithRange:range];
? ? ? ? ? ? ? ? ? dict[@"subStringRange"] = [NSValue valueWithRange:range];
? ? ? ? ? ? ? ? ? [initialArray addObject:dict];
? ? ? ? ? ? ? ? ? //遞歸調用
? ? ? ? ? ? ? ? ? [self searchAllTextRangeWithInitialArray:initialArray initialText:initialText regexString:regexString];
? ? ? ? ? ? }else{ ? ??
? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? }
? ? ? }else{//如果數組中已經有值了
? ? ? ? ? ? //1、取數組中最后一個字典,記錄后串在原串中的起始位置,把該串及其之前的串去掉生成新串
? ? ? ? ? ? NSMutableDictionary *lastDict = [initialArray lastObject];
? ? ? ? ? ? NSRangelastRange = [lastDict[@"subStringRange"]rangeValue];
? ? ? ? ? ? NSUIntegernewStringBeginLocation = lastRange.location+ lastRange.length;
? ? ? ? ? ? NSString*newString = [initialTextsubstringFromIndex:newStringBeginLocation];
? ? ? ? ? ? //2、在新串中找符合的子串,如果找到,包裝存進數組
? ? ? ? ? ? NSRange rangeInNewString = [newString rangeOfString:regexString options:NSRegularExpressionSearch];
? ? ? ? ? ? if(rangeInNewString.location!=NSNotFound) {
? ? ? ? ? ? ? ? ? //包裝字典,存進數組
? ? ? ? ? ? ? ? ? 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];
? ? ? ? ? ? ? ? ?//遞歸調用
? ? ? ? ? ? ? ? ?[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(@"查詢成功");
}
//此時,如果有對應的匹配項,數組中已經存好對應的字典了
備注:
1、array中存的是N個字典,每個字典中存了兩個值:子串、子串位置,結構如下圖
2、字典中的range是NSValue,需要轉換成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、上文中的是在網上找到的匹配一段文字中的鏈接的正則表達式,親測好用!如果需要匹配一段文字中的電話號碼、郵箱等,可以詢問度娘相關的表達式;
2、喜歡可以點個贊哦!轉載請說明出處,謝謝!