主な問題: ObjC は、パターンが の場合、6 つの一致があったことを教えてくれますが、パターン@"\\b(\\S+)\\b"
が の場合、@"A b (c) or (d)"
1 つの一致しか報告しません"c"
。
解決
キャプチャ グループを NSArray として返す関数を次に示します。私はObjective Cの初心者なので、可変配列を作成して最後にNSArrayに割り当てるよりも、扱いにくい作業を行うためのより良い方法があると思います。
- (NSArray *)regexWithResults:(NSString *)haystack pattern:(NSString *)strPattern
{
NSArray *ar;
ar = [[NSArray alloc] init];
NSError *error = NULL;
NSArray *arTextCheckingResults;
NSMutableArray *arMutable = [[NSMutableArray alloc] init];
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:strPattern
options:NSRegularExpressionSearch error:&error];
arTextCheckingResults = [regex matchesInString:haystack
options:0
range:NSMakeRange(0, [haystack length])];
for (NSTextCheckingResult *ntcr in arTextCheckingResults) {
int captureIndex;
for (captureIndex = 1; captureIndex < ntcr.numberOfRanges; captureIndex++) {
NSString * capture = [haystack substringWithRange:[ntcr rangeAtIndex:captureIndex]];
//NSLog(@"Found '%@'", capture);
[arMutable addObject:capture];
}
}
ar = arMutable;
return ar;
}
問題
Perl でキャプチャ グループを一致させるために、次のような方法で括弧を使用することに慣れています。
#!/usr/bin/perl -w
use strict;
my $str = "This sentence has words in it.";
if(my ($what, $inner) = ($str =~ /This (\S+) has (\S+) in it/)) {
print "That $what had '$inner' in it.\n";
}
そのコードは以下を生成します:
その文には「言葉」が含まれていました。
しかし、Objective C では、NSRegularExpression を使用すると、異なる結果が得られます。サンプル関数:
- (void)regexTest:(NSString *)haystack pattern:(NSString *)strPattern
{
NSError *error = NULL;
NSArray *arTextCheckingResults;
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:strPattern
options:NSRegularExpressionSearch
error:&error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:haystack options:0 range:NSMakeRange(0, [haystack length])];
NSLog(@"Pattern: '%@'", strPattern);
NSLog(@"Search text: '%@'", haystack);
NSLog(@"Number of matches: %lu", numberOfMatches);
arTextCheckingResults = [regex matchesInString:haystack options:0 range:NSMakeRange(0, [haystack length])];
for (NSTextCheckingResult *ntcr in arTextCheckingResults) {
NSString *match = [haystack substringWithRange:[ntcr rangeAtIndex:1]];
NSLog(@"Found string '%@'", match);
}
}
そのテスト関数を呼び出すと、結果は文字列内の単語数をカウントできることを示しています。
NSString *searchText = @"This sentence has words in it.";
[myClass regexTest:searchText pattern:@"\\b(\\S+)\\b"];
パターン: '\b(\S+)\b' 検索テキスト: 「この文には単語が含まれています。」 マッチ数: 6 文字列 'This' が見つかりました 文字列「文」が見つかりました 文字列「has」が見つかりました 文字列「words」が見つかりました 文字列「in」が見つかりました 文字列「それ」が見つかりました
しかし、キャプチャ グループが明示的である場合はどうなるでしょうか。
[myClass regexTest:searchText pattern:@".*This (sentence) has (words) in it.*"];
結果:
パターン: '.*This (文) has (words) in it.*' 検索テキスト: 「この文には単語が含まれています。」 マッチ数: 1 文字列「文」が見つかりました
上記と同じですが、実際の単語の代わりに \S+ を使用します:
[myClass regexTest:searchText pattern:@".*This (\\S+) has (\\S+) in it.*"];
結果:
パターン: '.*This (\S+) has (\S+) in it.*' 検索テキスト: 「この文には単語が含まれています。」 マッチ数: 1 文字列「文」が見つかりました
真ん中のワイルドカードはどうですか?
[myClass regexTest:searchText pattern:@"^This (\\S+) .* (\\S+) in it.$"];
結果:
パターン: '^This (\S+) .* (\S+) in it.$' 検索テキスト: 「この文には単語が含まれています。」 マッチ数: 1 文字列「文」が見つかりました
参照: NSRegularExpression NSTextCheckingResult NSRegularExpression マッチング オプション