2010-10-23 49 views
15

我想解析一個字符串並在中間獲得另一個字符串。在ObjC中的兩個其他字符串之間獲取字符串

即。

世界,你好這是一個字符串

我需要找到「世界」之間的字符串「是」(這)。我已經環顧四周,但還沒有弄清楚,主要是因爲我是Objective C的新手......任何人都知道如何使用RegEx或不使用?

回答

30

正則表達式的解決方案,雅克給人的作品,並警告要求iOS 4.0及更高版本是正確的。使用正則表達式也很慢,而且如果搜索表達式是已知的字符串常量,則會過度使用。

您可以使用NSStringNSScanner類中的方法來解決問題,這兩個方法自iPhone OS 2.0開始就已經可用,並且早在Mac OS X 10.0之前就已經可用:)。

那麼你想要的是什麼樣的NSString這樣的新方法?

@interface NSString (CWAddition) 
- (NSString*) stringBetweenString:(NSString*)start andString:(NSString*)end; 
@end 

沒問題,我們假設我們應該返回nil是不是可以找到這樣的字符串。

使用NSString只執行是相當直截了當:

@implementation NSString (NSAddition) 
- (NSString*) stringBetweenString:(NSString*)start andString:(NSString*)end { 
    NSRange startRange = [self rangeOfString:start]; 
    if (startRange.location != NSNotFound) { 
     NSRange targetRange; 
     targetRange.location = startRange.location + startRange.length; 
     targetRange.length = [self length] - targetRange.location; 
     NSRange endRange = [self rangeOfString:end options:0 range:targetRange]; 
     if (endRange.location != NSNotFound) { 
      targetRange.length = endRange.location - targetRange.location; 
      return [self substringWithRange:targetRange]; 
     } 
    } 
    return nil; 
} 
@end 

或者你可以使用NSScanner類做的實現:

@implementation NSString (NSAddition) 
- (NSString*) stringBetweenString:(NSString*)start andString:(NSString*)end { 
    NSScanner* scanner = [NSScanner scannerWithString:self]; 
    [scanner setCharactersToBeSkipped:nil]; 
    [scanner scanUpToString:start intoString:NULL]; 
    if ([scanner scanString:start intoString:NULL]) { 
     NSString* result = nil; 
     if ([scanner scanUpToString:end intoString:&result]) { 
      return result; 
     } 
    } 
    return nil; 
} 
@end 
+0

請注意,此解決方案不能確保世界和在字邊界。你可以添加更多的代碼來處理這個問題,但它可能會非常棘手,所以我建議只使用正則表達式(NSRegularExpression或者iOS 3的RegexKitLite)來更容易地處理所有的角落案例。做一些分析,看看你是否需要手動編碼解決方案。 – Jacques 2010-10-23 16:38:03

+0

謝謝!我也將不得不找到多次出現的字符串...... ie。 你好再見 我會假設我可以只添加另一個參數(發生),然後通過起始字符串循環X次,對吧?我應該能夠弄清楚,特別是因爲你給了我NSRange的起點等。再次感謝! – 2010-10-23 19:40:07

+0

是的,應該沒問題。只需使用先前搜索的範圍來限制下一個搜索的搜索範圍。 – PeyloW 2010-10-24 07:52:32

3

查看ICU user guide on regular expressions

如果你知道,我只是一個結果:

NSRegularExpression *regex = [NSRegularExpression 
    regularExpressionWithPattern:@"\bworld\s+(.+)\s+is\b" options:0 error:NULL] 

NSTextCheckingResult *result = [regex firstMatchInString:string 
    options:0 range:NSMakeRange(0, [string length]]; 

// Gets the string inside the first set of parentheses in the regex 
NSString *inside = [string substringWithRange:[result rangeAtIndex:1]]; 

的\者B肯定有世界前一個單詞邊界,是後(這樣的「hello world這不是一個字符串」止跌」 t匹配)。世界之後和之前的世界都會吞噬任何空白。 。+?找到你在找什麼,用?使它非貪婪,以便「hello world這是一個字符串hello world這是一個字符串」不會給你「這是一個字符串hello world這個」。

我會留給你弄清楚如何處理多個匹配。 NSRegularExpression文檔應該可以幫助你。

如果你想確保匹配沒有跨越句子邊界,你可以做(​​[^。] +?)而不是(。+?),或者你可以使用enumerateSubstringsInRange:options:usingBlock:on your字符串並在選項中傳遞NSStringEnumerationBySentences。

這東西都需要4.0+。如果您想支持3.0+,請查看RegexKitLite。

+0

謝謝您的幫助!我將需要支持OS3/iPad,因此目前不是一種選擇。一旦操作系統4出來的iPad我可以切換到這個實施使用正則表達式。 – 2010-10-23 19:34:55

1

如果碰巧只是字符串用空格,你可以使用下面的代碼分隔:要麼

[string componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] 

OR

NSMutableArray *parts = [NSMutableArray arrayWithCapacity:1]; 

NSScanner *scanner = [NSScanner scannerWithString:string]; 
NSString *token; 
while ([scanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceCharacterSet]] intoString:&token]) { 
    [parts addObject:token]; 
} 
12

只是一個簡單的修改PeyloW的回答,返回所有開始和結束字符串內的字符串:

-(NSMutableArray*)stringsBetweenString:(NSString*)start andString:(NSString*)end 
{ 

    NSMutableArray* strings = [NSMutableArray arrayWithCapacity:0]; 

    NSRange startRange = [self rangeOfString:start]; 

    for(;;) 
    { 

    if (startRange.location != NSNotFound) 
    { 

     NSRange targetRange; 

     targetRange.location = startRange.location + startRange.length; 
     targetRange.length = [self length] - targetRange.location; 

     NSRange endRange = [self rangeOfString:end options:0 range:targetRange]; 

     if (endRange.location != NSNotFound) 
     { 

     targetRange.length = endRange.location - targetRange.location; 
     [strings addObject:[self substringWithRange:targetRange]]; 

     NSRange restOfString; 

     restOfString.location = endRange.location + endRange.length; 
     restOfString.length = [self length] - restOfString.location; 

     startRange = [self rangeOfString:start options:0 range:restOfString]; 

     } 
     else 
     { 
     break; 
     } 

    } 
    else 
    { 
     break; 
    } 

    } 

    return strings; 

} 
+0

+1這就是我一直在尋找的。謝啦!! – 2014-08-02 10:59:58

+2

For others ..將另一個參數添加爲'originalString'並用它替換'self'。 – 2014-08-02 11:03:46

相關問題