swift 中带有 NSRegularExpressions 的可选捕获组

optional capture groups with NSRegularExpressions in swift

我想有多个可选的捕获组,我想访问它们对应的字符串。

looks/works 喜欢这样的东西:

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
}

使用 NSRegularExpression 检索捕获的潜台词并不容易。

首先,matches(in:range:)的结果是[NSTextCheckingResult],每个NSTextCheckingResult都没有匹配到像(first?, second)这样的元组。

如果要检索捕获的潜台词,需要使用rangeAt(_:) 方法从NSTextCheckingResult 获取范围。 rangeAt(0)表示匹配整个模式的范围,rangeAt(1)表示第一次捕获,rangeAt(2)表示第二次,以此类推。

rangeAt(_:)returns一个NSRange,而不是SwiftRange。内容(locationlength)基于 NSString.

的 UTF-16 表示

这是对您的目的最重要的部分,rangeAt(_:) returns NSRange(location: NSNotFound, length: 0) 对于每个丢失的捕获。

所以,你可能需要这样写:

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
}