Elvedin Hamzagic
Elvedin Hamzagic

Reputation: 855

Objective-C, regular expression match repetition

I found a problem in regular expression to match all group repetition.

This is a simple example:

NSString *string = @"A1BA2BA3BC";
NSString *pattern = @"(A[^AB]+B)+C";

NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
NSArray *array = [regex matchesInString:string options:0 range:NSMakeRange(0, [string length])];

Returning array have one element which contains two ranges, whole input string and last captured group "A3B". First two groups, "A1B" and "A2B", are not captured as I expected.

I've tried all from greedy to lazy matching.

Upvotes: 1

Views: 2724

Answers (1)

zx81
zx81

Reputation: 41838

A Quantifier Does not Spawn New Capture Groups

Except in .NET, which has CaptureCollections, adding a quantifier to a capture group does not create more captures. The group number stays the same (in your case, Group 1), and the content returned is the last capture of the group.

Reference

Everything about Regex Capture Groups (see Generating New Capture Groups Automatically)

Iterating the Groups

If you wanted to match all the substrings while still validating that they are in a valid string (composed of such groups and ending in C), you could use:

 A[^AB]+B(?=(?:A[^AB]+B)*C)

The whole string, of course, would be

^(?:A[^AB]+B)+C$

To iterate the substrings: something like

NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"A[^AB]+B(?=(?:A[^AB]+B)*C)" options:0 error:&error];
NSArray *matches = [regex matchesInString:subject options:0 range:NSMakeRange(0, [subject length])];
NSUInteger matchCount = [matches count];
if (matchCount) {
    for (NSUInteger matchIdx = 0; matchIdx < matchCount; matchIdx++) {
        NSTextCheckingResult *match = [matches objectAtIndex:matchIdx];
        NSRange matchRange = [match range];
        NSString *result = [subject substringWithRange:matchRange];
    }
}
else {  // Nah... No matches.
     }

Upvotes: 1

Related Questions