I want to have multiple capture groups that can be optional and I want to access the strings they correspond to.
Something that looks/works like this:
let text1 = "something with foo and bar"
let text2 = "something with just bar"
let regex = NSRegularExpression(pattern: "(foo)? (bar)")
for (first?, second) in regex.matches(in:text1) {
print(first) // foo
print(second) // bar
}
for (first?, second) in regex.matches(in:text2) {
print(first) // nil
print(second) // bar
}
Retrieving captured subtext with
NSRegularExpression
is not so easy.First of all, the result of
matches(in:range:)
is[NSTextCheckingResult]
, and eachNSTextCheckingResult
does not match to tuple like(first?, second)
.If you want to retrieve captured subtext, you need to get the range from the
NSTextCheckingResult
withrangeAt(_:)
method.rangeAt(0)
represents the range matching the whole pattern,rangeAt(1)
for the first capture,rangeAt(2)
for the second, and so on.And
rangeAt(_:)
returns anNSRange
, not SwiftRange
. The content (location
andlength
) is based on the UTF-16 representation ofNSString
.And this is the most important part for your purpose,
rangeAt(_:)
returnsNSRange(location: NSNotFound, length: 0)
for each missing capture.So, you may need to write something like this: