3

主な問題: 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 マッチング オプション

4

2 に答える 2

7

変わればいいと思う

// returns the range which matched the pattern
NSString *match = [haystack substringWithRange:ntcr.range];

// returns the range of the first capture
NSString *match = [haystack substringWithRange:[ntcr rangeAtIndex:1]];

単一のキャプチャを含むパターンの場合、期待される結果が得られます。

NSTextCheckingResult:rangeAtIndex のドキュメント ページを参照してください。

結果には少なくとも 1 つの範囲が必要ですが、必要に応じてそれ以上の範囲を指定することもできます (たとえば、正規表現キャプチャ グループを表すため)。

rangeAtIndex を渡す: 値 0 は、常に range プロパティの値を返します。追加の範囲がある場合は、1 から numberOfRanges-1 までのインデックスを持ちます。

于 2011-09-29T16:25:25.873 に答える
1

変更NSTextCheckingResult:

- (void)regexTest:(NSString *)haystack pattern:(NSString *)strPattern
{
    NSError *error = NULL;
    NSArray *arTextCheckingResults;

    NSRegularExpression *regex = [NSRegularExpression
                                  regularExpressionWithPattern:strPattern
                                  options:NSRegularExpressionSearch
                                  error:&error];
    NSRange stringRange = NSMakeRange(0, [haystack length]);
    NSUInteger numberOfMatches = [regex numberOfMatchesInString:haystack
                                                        options:0 range:stringRange];

    NSLog(@"Number of matches for '%@' in '%@': %u", strPattern, haystack, numberOfMatches);

    arTextCheckingResults = [regex matchesInString:haystack options:NSRegularExpressionCaseInsensitive range:stringRange];

    for (NSTextCheckingResult *ntcr in arTextCheckingResults) {
        NSRange matchRange = [ntcr rangeAtIndex:1];
        NSString *match = [haystack substringWithRange:matchRange];
        NSLog(@"Found string '%@'", match);
    }
}

NSLog 出力:
文字列 'words' が見つかりました

于 2011-09-29T16:22:26.293 に答える