NSRegularExpression cannot find capturing group matches
Asked Answered
U

1

5

I'm trying to parse a string using one regular expression pattern.

Here is the pattern:

(\")(.+)(\")\s*(\{)

Here is the text to be parsed:

"base" {

I want to find these 4 capturing groups:

1. "
2. base
3. "
4. {

I am using the following code trying to capture those groups

class func matchesInCapturingGroups(text: String, pattern: String) -> [String] {
    var results = [String]()

    let textRange = NSMakeRange(0, count(text))
    var index = 0

    if let matches = regexp(pattern)?.matchesInString(text, options: NSMatchingOptions.ReportCompletion, range: textRange) as? [NSTextCheckingResult] {
        for match in matches {
            // this match = <NSExtendedRegularExpressionCheckingResult: 0x7fac3b601fd0>{0, 8}{<NSRegularExpression: 0x7fac3b70b5b0> (")(.+)(")\s*(\{) 0x1}
            results.append(self.substring(text, range: match.range))
        }
    }

    return results
}

Unfortunately it is able to find only one group with range (0, 8) which is equal to: "base" {. So it finds one group which is the entire string instead of 4 groups.

Is that even possible to get those groups using NSRegularExpression?

Unreasonable answered 19/7, 2015 at 8:14 Comment(7)
@stribizhev you have to escape the \s to \\s as well.Gynoecium
I have not done it myself, but from the documentation of NSTextCheckingResult I would have to ask: Have you tried checking match.numberOfRanges and match.rangeAtIndex?Benghazi
@luk2302, Yeah I know, I copy paste it from regex101.com when I'm playing with expressions so it has not been escaped.Unreasonable
@Sascha Kolberg - yes I tried. result was the same.Unreasonable
@TomaszSzulc I wrote an answer that works... you might want to check that one out.Gynoecium
Yeah I am playing with that a bit right now. Will confirm if works :)Unreasonable
Possible duplicate of #31103910.Cambium
G
7

Yes, of course it is possible. You just have to change your current logic for finding the actual groups:

func matchesInCapturingGroups(text: String, pattern: String) -> [String] {
    var results = [String]()

    let textRange = NSMakeRange(0, text.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))

    do {
        let regex = try NSRegularExpression(pattern: pattern, options: [])
        let matches = regex.matchesInString(text, options: NSMatchingOptions.ReportCompletion, range: textRange)

        for index in 1..<matches[0].numberOfRanges {
            results.append((text as NSString).substringWithRange(matches[0].rangeAtIndex(index)))
        }
        return results
    } catch {
        return []
    }
}

let pattern = "(\")(.+)(\")\\s*(\\{)"
print(matchesInCapturingGroups("\"base\" {", pattern: pattern))

You actually only get 1 match. You have to go into that match and in there you will find the captured groups. Note that I omit the first group since the first group represents the entire match.

This will output

[""", "base", """, "{"]

Note the escaped regex string and make sure that you are using the same one.

Gynoecium answered 19/7, 2015 at 8:43 Comment(2)
Thanks for this. Okay I thought I should get multiple matches but there is one match with multiple ranges. Now it is clear.Unreasonable
for index in 1..<matches[0].numberOfRanges Will this cause a crash if there are no matches to the expression because it's accessing an element of an empty array?Desmond

© 2022 - 2024 — McMap. All rights reserved.