Swift 3 - 如何在正则表达式中提取捕获的组?

nob*_*are 9 regex swift swift3

我正在使用Swift 3并尝试访问捕获的组.

let regexp = "((ALREADY PAID | NOT ALR | PROVIDER MAY | READY | MAY BILL | BILL YOU | PAID)((.|\\n)*))(( \\d+)(\\.+|-+)(\\d\\d))"

// check if some substring is in the recognized text
if let range = stringText.range(of:regexp, options: .regularExpression) {
    let result = tesseract.recognizedText.substring(with:range)
}
Run Code Online (Sandbox Code Playgroud)

我希望能够提取出捕获的最后两个数字(\d\d),所以如果文本是:ALREADY PAID asfasdfadsfasdf 39.15,它将提取15.这是一个正则表达式构建器,显示我想要的内容.通常情况下,我可以做到$8第8组被提取,但我不知道如何在Swift 3中做到这一点.

http://regexr.com/3fh1e

mat*_*att 21

但我不知道如何在Swift 3中这样做.

当您收到来自NSRegularExpression的匹配项时,您获得的是NSTextCheckingResult.您打电话rangeAt来获取特定的捕获组.

例:

let s = "hey ho ha"
let pattern = "(h).*(h).*(h)"
// our goal is capture group 3, "h" in "ha"
let regex = try! NSRegularExpression(pattern: pattern)
let result = regex.matches(in:s, range:NSMakeRange(0, s.utf16.count))
let third = result[0].rangeAt(3) // <-- !!
third.location // 7
third.length // 1
Run Code Online (Sandbox Code Playgroud)

  • 第三个是`NSRange`,你如何将它转换成`s.substring`中使用它所需的`Range`类型?否则,这里的“h”结果在哪里?是将 s 转换为 NSString 的唯一方法吗?有没有更简单的方法来使用正则表达式?这看起来太过分了。 (2认同)

Vya*_*lav 8

雨燕4,雨燕5

extension String {
    func groups(for regexPattern: String) -> [[String]] {
    do {
        let text = self
        let regex = try NSRegularExpression(pattern: regexPattern)
        let matches = regex.matches(in: text,
                                    range: NSRange(text.startIndex..., in: text))
        return matches.map { match in
            return (0..<match.numberOfRanges).map {
                let rangeBounds = match.range(at: $0)
                guard let range = Range(rangeBounds, in: text) else {
                    return ""
                }
                return String(text[range])
            }
        }
    } catch let error {
        print("invalid regex: \(error.localizedDescription)")
        return []
    }
}
}
Run Code Online (Sandbox Code Playgroud)

例:

let res = "1my 2own 3string".groups(for:"(([0-9]+)[a-z]+) ")
Run Code Online (Sandbox Code Playgroud)

(lldb)po res?2个要素
?0:3个元素

- 0 : "1my "

- 1 : "1my"

- 2 : "1"   
Run Code Online (Sandbox Code Playgroud)

?1:3个元素

- 0 : "2own "

- 1 : "2own"

- 2 : "2"
Run Code Online (Sandbox Code Playgroud)

  • 哇,很高兴看到“现代语言”Swift 用 25 年历史的 Javascript 做一些需要 2 行代码的事情‍♂️ (3认同)

Con*_*lon 6

与以往一样,简单的扩展似乎是围绕斯威夫特奇怪的过度复杂的方式......

extension NSTextCheckingResult {
    func groups(testedString:String) -> [String] {
        var groups = [String]()
        for i in  0 ..< self.numberOfRanges
        {
            let group = String(testedString[Range(self.range(at: i), in: testedString)!])
            groups.append(group)
        }
        return groups
    }
}
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

if let match = myRegex.firstMatch(in: someString, range: NSMakeRange(0, someString.count)) {
     let groups = match.groups(testedString: someString)
     //... do something with groups
}
Run Code Online (Sandbox Code Playgroud)