我希望有多个可选的捕获组,我想访问它们对应的字符串。
看起来像这样的东西:
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
}
答案 0 :(得分:2)
使用NSRegularExpression
检索捕获的子文章并不容易。
首先,matches(in:range:)
的结果为[NSTextCheckingResult]
,而每个NSTextCheckingResult
与(first?, second)
之类的元组不匹配。
如果要检索捕获的子文本,则需要使用NSTextCheckingResult
和rangeAt(_:)
方法获取范围。 rangeAt(0)
表示与整个模式匹配的范围,第一次捕获为rangeAt(1)
,第二次捕获为rangeAt(2)
,依此类推。
rangeAt(_:)
返回NSRange
,而不是Swift Range
。内容(location
和length
)基于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
}