Objective-C

正規表現にマッチする部分を区切りとしてNSStringを分割

More than 5 years have passed since last update.

ちなみに、以下のようなことをするメソッドはすでにあった。


  • 文字列をデリミタとして分割する

  • 文字集合(NSCharacterSet)にマッチする部分を区切りとして分割する

  • 正規表現にマッチした部分全ての配列を返す。rubyとかでいうところのString#scan。あるいはマッチした部分を引数にとるブロックを実行する。

だけども正規表現にマッチするとこを区切りとして分割するメソッドがなかったので実装してみた。

#import "Foundation/Foundation.h"


@interface NSString (RegularExpression)
// 正規表現で分割した文字列の配列を返す
- (NSArray *)componentsSeparatedByRegularExpression:(NSRegularExpression *)regexp;
// 正規表現で分割した文字列を引数にとるブロックを実行する
- (void)componentsSeparatedByRegularExpression:(NSRegularExpression *)regexp
usingBlock:(void (^)(NSString *))block;
@end

@implementation NSString (RegularExpression)
- (NSArray *)componentsSeparatedByRegularExpression:(NSRegularExpression *)regexp {
NSMutableArray *result = [NSMutableArray array];
[self componentsSeparatedByRegularExpression:regexp
usingBlock:^(NSString *component) {
[result addObject:component];
}];
return result;
}

- (void)componentsSeparatedByRegularExpression:(NSRegularExpression *)regexp
usingBlock:(void (^)(NSString *))block {
__block int startPage = 0;
[regexp enumerateMatchesInString:self
options:0
range:NSMakeRange(0, self.length)
usingBlock:^(NSTextCheckingResult *match,
NSMatchingFlags flag,
BOOL *stop) {
NSUInteger matchLocation = match.range.location;
NSUInteger matchLength = match.range.length;

block([self substringWithRange:NSMakeRange(startPage, matchLocation - startPage)]);
startPage = matchLocation + matchLength;
}];
block([self substringWithRange:NSMakeRange(startPage, self.length - startPage)]);
}
@end

// 使用例
int main(int argc, char **argv) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSError *error = nil;
NSRegularExpression *re =
[NSRegularExpression regularExpressionWithPattern:@"-{2,}\n"
options:NSRegularExpressionDotMatchesLineSeparators
error:&error];
NSString *text = @""
"あああ\n"
"----\n"
"いいい\n"
"いいい\n"
"いいい\n"
"----\n"
"いいい\n";

[text componentsSeparatedByRegularExpression:re
usingBlock:^(NSString *component) {
NSLog(@"%@", component);
}];

for (NSString *component in [text componentsSeparatedByRegularExpression:re]) {
NSLog(@"%@", component);
}

[pool release];

return 0;
}