mike-neckのブログ

Java or Groovy or Swift or Golang

Swift 用の正規表現ライブラリー

これは Qiita のアドベントカレンダー2018 の19日目のエントリーです。

qiita.com

Swift の勉強を始めたのが今年の5月末からで、約半年程度 Swift をやってきました。ただ、僕は仕事では一切 Swift を書いていないので、知見に溢れた他の方のエントリーを楽しみにしています(突然の煽り)。

f:id:mike_neck:20180609045321p:plain


Swift を勉強し始めて3ヶ月くらいの頃に、ふとしたきっかけで正規表現が欲しくなりました。調べてみたところどうやら Swift 単体で使える正規表現がなく、 NSRegularExpression を使って、結構面倒そうなコードを書くらしいということがわかりました。しかし、これが Linux で使えるのかわからない(実際には使える)ので、その時は正規表現を使わない方法でとりあえず回避しました。

また、後日、詳しそうな人に尋ねたところ、 NSRegularExpression をラップして String などの extension とするライブラリーを自作しているとのことでした。 実際、 GitHub で 「 Swift regex 」 で調べてみると、そのようなライブラリーがたくさんあるようです。


というわけで、そのようなライブラリーを使えばよいのですが、 Swift の勉強がてら正規表現ライブラリーを作ってみるのも面白そうだと思い、作ってみることにしました。レポジトリーはこちらです。

github.com


仕組み

仕組みはいたって簡単で、 C 言語の正規表現ライブラリーをラップしているだけです。今のところ POSIX正規表現(regex.h)をラップしたもののみを提供しています。Swift から C 言語を呼び出す方法等は過去にエントリーを書いているので、そちらを見ると良いと思います。

mike-neck.hatenadiary.com

mike-neck.hatenadiary.com


導入方法

Swift Package Manager を使います。残念ながらその他のビルドシステムの方法は知らないので、PRくれるとノールックでマージすると思います。

次の依存ライブラリーを追加します。

  dependencies [
    .package(url: "https://github.com/mike-neck/swift-regex.git", from: "0.1"),
  ]

ターゲットに加えます。

targets [
    .target(name: "YourAwesomeApp", dependencies: [
        "SwiftRegex",
        "POSIXRegex",
    ]),
]

このライブラリーには今のところ3つモジュールがあります。

  • SwiftRegex - API を定めているモジュール
  • POSIXRegex - APIPOSIX 実装モジュールで、次の CPOSIXRegex モジュールをラップしています
  • CPOSIXRegex - POSIX正規表現を呼び出す C で書かれたモジュール

これらのうち、 API と 実装モジュールをターゲットに加えれば、このライブラリーを利用できます。


コード例

import POSIXRegex
import SwiftRegex

SwiftRegexImplementation.by.usePosix() // 1

guard let regex = pattern(of: "ba").compile() else { // 2
    fatalError { "cannot compile pattern \"ba\"" }
} 

let matcher = regex.matcher(for: "foo-bar-baz") //3
matcher.matches // -> true //4
  1. SwiftRegexSwiftRegexImplementation という長ったらしい名前の構造体があり、それの static プロパティ byusePosix() という関数が生えているので、これを呼び出すと、 POSIX 実装の正規表現が使えます。
  2. pattern(of:) という関数があるので、それを呼び出してからコンパイルします。コンパイルの結果は SwiftRegex? となっており、正規表現が間違えているなどコンパイルできない場合は nil が返ってきます。
  3. 検索ソースの文字列を matcher(for:) 関数にわたすと検索結果が返ってきます
  4. 今のところ matches プロパティで検索結果だけが取り出せるようになっています。(今後、置換を実装していこうと思っています)

という感じのライブラリーですが、どうやら Swift5 以降に正規表現が加わるかもしれないそうなので短命に終わるかもしれないです。「へぇ〜」と思ったそこのアナタ!、ぜひGitHubでスターを付けてってください!【2018/12/19 15:45 間違えているので修正しました】