0

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

看起来/像这样工作的东西:

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
}
4

1 回答 1

6

检索捕获的潜台词NSRegularExpression并不那么容易。

首先,matches(in:range:)is的结果[NSTextCheckingResult],且 eachNSTextCheckingResult不匹配 tuple like (first?, second)

如果要检索捕获的潜文本,则需要从NSTextCheckingResultwithrangeAt(_:)方法中获取范围。rangeAt(0)表示匹配整个模式的范围,rangeAt(1)第一次捕获,rangeAt(2)第二次,依此类推。

rangeAt(_:)返回一个NSRange,而不是 Swift Range。内容 (locationlength) 基于 的 UTF-16 表示NSString

对于您的目的而言,这是最重要的部分,为每个丢失的捕获rangeAt(_:)返回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
}
于 2016-12-03T21:17:35.873 回答