swift中带有NSRegularExpressions的可选捕获组

时间:2016-12-03 18:26:57

标签: ios swift nsregularexpression capture-group

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

看起来像这样的东西:

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 个答案:

答案 0 :(得分:2)

使用NSRegularExpression检索捕获的子文章并不容易。

首先,matches(in:range:)的结果为[NSTextCheckingResult],而每个NSTextCheckingResult(first?, second)之类的元组不匹配。

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

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

这是您最重要的部分,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
}