optional capture groups with NSRegularExpressions in swift

天大地大妈咪最大 提交于 2019-12-25 07:32:06

问题


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
}

回答1:


Retrieving captured subtext with NSRegularExpression is not so easy.

First of all, the result of matches(in:range:) is [NSTextCheckingResult], and each NSTextCheckingResult does not match to tuple like (first?, second).

If you want to retrieve captured subtext, you need to get the range from the NSTextCheckingResult with rangeAt(_:) 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 an NSRange, not Swift Range. The content (location and length) is based on the UTF-16 representation of NSString.

And this is the most important part for your purpose, rangeAt(_:) returns NSRange(location: NSNotFound, length: 0) for each missing capture.

So, you may need to write something like this:

let text1 = "something with foo and bar"
let text2 = "something with just bar"
let regex = try! NSRegularExpression(pattern: "(?:(foo).*)?(bar)") //please find a better example...

for match in regex.matches(in: text1, range: NSRange(0..<text1.utf16.count)) {
    let firstRange = match.rangeAt(1)
    let secondRange = match.rangeAt(2)
    let first = firstRange.location != NSNotFound ? (text1 as NSString).substring(with: firstRange) : nil
    let second = (text1 as NSString).substring(with: secondRange)
    print(first) // Optioonal("foo")
    print(second) // bar
}

for match in regex.matches(in: text2, range: NSRange(0..<text2.utf16.count)) {
    let firstRange = match.rangeAt(1)
    let secondRange = match.rangeAt(2)
    let first = firstRange.location != NSNotFound ? (text2 as NSString).substring(with: firstRange) : nil
    let second = (text2 as NSString).substring(with: secondRange)
    print(first) // nil
    print(second) // bar
}


来源:https://stackoverflow.com/questions/40951099/optional-capture-groups-with-nsregularexpressions-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!