2016-12-03 31 views
0

我想拥有多个捕获组,这些捕获组可以是可选的,我想访问它们对应的字符串。在swift中使用NSRegularExpressions的可选捕获组

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

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

检索捕获的潜台词与NSRegularExpression也不是那么容易。

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

如果要检索捕获的潜台词,则需要使用rangeAt(_:)方法得到NSTextCheckingResult的范围。 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 
}