michaelsnowden
michaelsnowden

Reputation: 6192

Regex for Text Within Braces

I'm a total noob to regexes. I'm trying to come up with a regex that will capture text in braces. Example:

{t} this text shouldn't {1}{2} be captured {3} -> t, 1, 2, 3

This is what I've tried:

NSString *text = @"{t} this text shouldn't {1}{2} be captured {3}";
NSString *pattern = @"\\{.*\\}";    // The part I need help with
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
                                                                       options:kNilOptions
                                                                         error:nil];
NSArray *matches = [regex matchesInString:text
                                  options:kNilOptions
                                    range:NSMakeRange(0, text.length)];
for (NSTextCheckingResult *result in matches)
{
    NSString *match = [text substringWithRange:result.range];
    NSLog(@"%@%@", match , (result == matches.lastObject) ? @"" : @", ");
}

It yielded {t} this text shouldn't {1}{2} be captured {3}.

I'm sorry for such a straightforward request, but I'm just in a hurry and I don't know much about regexes.

Upvotes: 1

Views: 171

Answers (1)

zx81
zx81

Reputation: 41838

Lookahead and Lookbehind

NSRegularExpressions support lookarounds, so we can use this simple regex:

(?<=\{)[^}]+(?=\})

See the matches in the regex demo.

To iterate over all the matches, use this:

NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(?<=\\{)[^}]+(?=\\})" options:NSRegularExpressionAnchorsMatchLines 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.
     }

Explanation

  • The lookbehind (?<=\{) asserts that what precedes the current position is an opening brace
  • [^}]+ matches all chars that are not a closing brace
  • The lookahead (?=\}) asserts that what follows is a closing brace

Reference

Upvotes: 2

Related Questions