【问题标题】:Get String Between Two Other Strings in ObjC在 ObjC 中获取其他两个字符串之间的字符串
【发布时间】:2010-10-23 03:40:46
【问题描述】:

我正在尝试解析一个字符串并在中间获取另一个字符串。

即。

Hello world 这是一个字符串

我需要找到“world”和“is”(this)之间的字符串。我环顾四周,但还没有弄明白,主要是因为我是 Objective C 的新手......有人知道如何做到这一点,无论是否使用 RegEx?

【问题讨论】:

    标签: iphone objective-c


    【解决方案1】:

    Jacques 提供的正则表达式解决方案有效,并且需要 iOS 4.0 及更高版本的警告是正确的。使用正则表达式也很慢,如果搜索表达式是已知的字符串常量,那就有点过分了。

    您可以使用NSString 上的方法或名为NSScanner 的类来解决问题,这两种方法都可以从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
    

    【讨论】:

    • 请注意,此解决方案不能确保 world 和 is 在单词边界上。你可以添加更多代码来处理这个问题,但这可能会很棘手,所以我建议只使用正则表达式(iOS 3 的 NSRegularExpression 或 RegexKitLite)来更容易处理所有极端情况。做一些分析,看看是否需要手动编写解决方案。
    • 谢谢!我还必须找到多次出现的字符串......即。 HelloBye 我会假设我可以添加另一个参数(出现),然后循环起始字符串 X 次,对吗?我应该能弄明白,尤其是你给了我 NSRange 的起点等。再次感谢!
    • 是的,应该没问题。只需使用上一次搜索的范围来限制下一次搜索的搜索范围即可。
    • 很好的答案,但是在 NSString 扩展解决方案中,您应该防止在 NSRange endRange = [self rangeOfString:end options:0 range:targetRange];语句,否则会崩溃: NSRange checkEndRange = [self rangeOfString:end]; if (checkEndRange.location != NSNotFound)
    【解决方案2】:

    只是对 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;
    
    }
    

    【讨论】:

    • 对于其他人.. 再添加一个参数作为 'originalString' 并用它替换 'self'。
    【解决方案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 确保在 world 之前和 is 之后有一个单词边界(因此“hello world 这不是字符串”不匹配)。 \s 吞噬了世界之后和之前的任何空白。 .+?使用 ? 查找您要查找的内容使其不贪婪,这样“hello world 这是一个字符串 hello world 这是一个字符串”不会给你“this a string hello world this”。

    我将由您来决定如何处理多个匹配项。 NSRegularExpression 文档应该可以帮助您。

    如果您想确保匹配不会跨越句子边界,您可以使用 ([^.]+?) 而不是 (.+?),或者您可以在字符串上使用 enumerateSubstringsInRange:options:usingBlock:并在选项中传递 NSStringEnumerationBySentences。

    这些东西都需要4.0+。如果您想支持 3.0+,请查看 RegexKitLite。

    【讨论】:

    • 感谢您的帮助!我需要支持 OS3/iPad,所以目前这不是一个选项。一旦 OS 4 出现在 iPad 上,我就可以使用 Regex 切换到这个实现。
    【解决方案4】:

    如果它恰好是由空格分隔的字符串,您可以使用以下代码:要么

    [string componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]
    

    或

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-21
      • 1970-01-01
      相关资源
      最近更新 更多