3

主要问题:当我的模式为 时,ObjC 可以告诉我有六个匹配项@"\\b(\\S+)\\b",但是当我的模式为 时@"A b (c) or (d)",它只报告一个匹配项,"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'
    找到字符串“句子”
    找到字符串“有”
    找到字符串“单词”
    找到字符串 'in'
    找到字符串“它”

但是如果捕获组是明确的,像这样呢?

[myClass regexTest:searchText pattern:@".*This (sentence) has (words) in it.*"];

结果:

    模式:'.*这个(句子)里面有(单词)。*'
    搜索文本:“这句话中有单词。”
    匹配数:1
    找到字符串“句子”

与上面相同,但使用 \S+ 而不是实际单词:

[myClass regexTest:searchText pattern:@".*This (\\S+) has (\\S+) in it.*"];

结果:

    模式:'.*这个 (\S+) 里面有 (\S+)。*'
    搜索文本:“这句话中有单词。”
    匹配数: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 的文档页面:

结果必须至少有一个范围,但可以选择有更多(例如,表示正则表达式捕获组)。

传递 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 回答