2016-12-03 9 views
0

Я хочу иметь несколько групп захвата, которые могут быть необязательными, и я хочу получить доступ к строкам, которым они соответствуют.необязательные группы захвата с помощью NSRegularExpressions в swift

Что-то, что выглядит/работает так:

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).

Если вы хотите получить захваченный подтекст, вам необходимо получить диапазон от NSTextCheckingResult с помощью метода rangeAt(_:). rangeAt(0) представляет диапазон, соответствующий всему рисунку, rangeAt(1) для первого захвата, rangeAt(2) для второго и так далее.

И rangeAt(_:) возвращает NSRange, а не Swift Range. Содержание (location и length) основано на представлении 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 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^