正则表达式,指定可选的捕获组?

时间:2012-02-09 15:32:28

标签: objective-c regex

有没有办法编写一个正则表达式模式,它将根据输入文本创建一个或两个组。 (即)

// ONE
NSString *pattern = @""; ([0-9]+).([0-9]+)
NSString *inputText = @"ThisIs MyTest72.56String";
// OUTPUT match = 72.56, group1 = 72, group2 = 56

我想要的是:

// TWO
NSString *pattern = @""; ([0-9]+).([0-9]+)
NSString *inputText = @"ThisIs MyTest72String";
// OUTPUT match = 72, group1 = 72, group2 = Empty

我以为我可以使用(?:)但这只是删除了组

我所追求的是:

Text = "ThisIs MyTest72String"
Match = 72
Group1 = 72
Group2 = Empty

Text = "ThisIs MyTest72.56String"
Match = 72.56
Group1 = 72
Group2 = 56

编辑:

这种作品虽然我想在最初的比赛中摆脱“S”。

Pattern = ([0-9]+).([0-9]*)
Text = "ThisIs MyTest72String"
Match = 72S
Group1 = 72    //RangeAtIndex:1 {13,2}
Group2 = Empty //RangeAtIndex:2 {16,0}

Text = "ThisIs MyTest72.56String"
Match = 72.56
Group1 = 72
Group2 = 56

这很接近,但在“Empty”(Group2)的情况下,我期望rangeAtIndex:2等于NSNotFound。文档说“如果其中一个捕获组没有参与此特定匹配,则返回范围{NSNotFound,0}”该组是否为空而不计为“未参与”?

3 个答案:

答案 0 :(得分:1)

这会给你你想要的吗?

([0-9]+)(?:\.([0-9]+))?

我已经转义了小数位(你没有,不确定你的目标语言是否需要它)并将小数及其后的所有内容分组为可选的非捕获组。

应该只是检查是否存在第二组。

答案 1 :(得分:1)

使用此模式:

pattern = @"([0-9]+)\.([0-9]+)?";

然后在NSTextCheckingResult检查组范围位置是否为NSNotFound

示例代码:

NSString *pattern = @"([0-9]+).([0-9]+)?";
NSString *string = @"ThisIs MyTest72.56String";
//NSString *string = @"ThisIs MyTest72.XXString";

NSRegularExpression *regex = [NSRegularExpression
                              regularExpressionWithPattern:pattern
                              options:NSRegularExpressionCaseInsensitive
                              error:nil];

NSTextCheckingResult *match = [regex firstMatchInString:string options:0 range:NSMakeRange(0, string.length)];

for (int groupNumber=1; groupNumber<match.numberOfRanges; groupNumber+=1) {
    NSRange groupRange = [match rangeAtIndex:groupNumber];
    if (groupRange.location != NSNotFound)
        NSLog(@"match %d: '%@'", groupNumber, [string substringWithRange:groupRange]);
    else
        NSLog(@"match %d: '%@'", groupNumber, @"");
}

NSLog输出:

匹配1:'72'
比赛2:'56'
使用第二种模式“匹配2:''”。

答案 2 :(得分:1)

这个怎么样:

NSString *inputText = @"ThisIs MyTest72.56String";
// Setup an NSError object to catch any failures
NSError *error = NULL;  
// create the NSRegularExpression object and initialize it with a pattern
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\d+.\\d+" options:NSRegularExpressionCaseInsensitive error:&error];
// create an NSRange object using our regex object for the first match in the string httpline
NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:inputText options:0 range:NSMakeRange(0, [inputText length])];
// check that our NSRange object is not equal to range of NSNotFound
if (!NSEqualRanges(rangeOfFirstMatch, NSMakeRange(NSNotFound, 0))) {
    // Since we know that we found a match, get the substring from the parent string by using our NSRange object
    NSString *substringForFirstMatch = [inputText substringWithRange:rangeOfFirstMatch];
    NSLog(@"Extracted string: %@",substringForFirstMatch); // Extracted string: 72.56

regex = [NSRegularExpression regularExpressionWithPattern:@"\\d+" options:NSRegularExpressionCaseInsensitive error:&error];
NSArray *matches = [regex matchesInString:substringForFirstMatch options:0 range:NSMakeRange(0, [substringForFirstMatch length])];
for (NSTextCheckingResult *match in matches) {
    NSString *matchString = [substringForFirstMatch substringWithRange:[match range]];
    NSLog(@"match string: %@", matchString);
    // match string: 72
    // match string: 56
}

}