Получить строку между двумя другими строками в ObjC

Я пытаюсь разобрать строку и получить другую строку посередине.

т.

Привет, мир, это строка

Мне нужно найти строку между "world" и "is" (это). Я огляделся, но еще не смог понять, в основном потому, что я новичок в Objective C... У кого-нибудь есть идея, как это сделать, с RegEx или без?

Ответы

Ответ 1

Решение регулярных выражений, которое Жак дает, и оговорка о требованиях к 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

Ответ 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;

}

Ответ 3

См. Руководство пользователя ICU для регулярных выражений.

Если вы знаете, что будет только один результат:

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 гарантирует, что граница слова перед миром и после (так что "привет мир это не строка" не будет соответствовать).\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\W \. +? находит то, что вы ищете, с помощью? делая его неживым, так что "hello world this is the world hello world this is a string" не дает вам "эту строку hello world this".

Я оставлю это для вас, чтобы выяснить, как обрабатывать несколько совпадений. Документация NSRegularExpression должна помочь вам.

Если вы хотите убедиться, что совпадение не пересекает границы предложения, вы можете сделать ([^.] +?) вместо (. +?), или вы можете использовать enumerateSubstringsInRange: options: usingBlock: на вашей строке и передайте NSStringEnumerationBySentences в параметрах.

Все это требует 4.0+. Если вы хотите поддерживать 3.0+, посмотрите в RegexKitLite.

Ответ 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];
}