🍁

Swift: 正規表現を使って文字列を抜き出す(グループ化対応)

2020/11/27に公開

Javascriptのmatchみたいなことをしたい。

import Foundation

extension String {
    func match(_ pattern: String) -> [String] {
        let range = NSRange(location: 0, length: self.count)
        guard let regex = try? NSRegularExpression(pattern: pattern),
              let matched = regex.firstMatch(in: self, range: range)
        else { return [] }
        return (0 ..< matched.numberOfRanges).compactMap { i in
            let r = matched.range(at: i)
            if r.location == NSNotFound { return nil }
            return NSString(string: self).substring(with: r)
        }
    }
}
使用例
let str = "Hello --<Kyome:1234>--"
let res = str.match(#"--<(([a-zA-Z]+):\d+)>--"#)
Swift.print(res)
["--<Kyome:1234>--", "Kyome:1234", "Kyome"]

一致文字列が配列で手に入る。グループ化している場合は大きい部分一致から細かい部分一致に向かって配列に格納されていく。
正規表現文字列を書くときは、正規表現のエスケープとSwiftのエスケープの双方を考えないといけなくなると面倒くさいので、Swift側のエスケープを無視できるように文字列は""ではなく#""#で囲うと良い。

Discussion