Node.jsでglobパターンを、RegExpに変換するBetterな法方

小ネタです。

結論

以下のコードでglobの文字列をRegExpの文字列に変換することができました。

const minimatch = require('minimatch').Minimatch;
const globToRegExp = glob => {
  const regexp = new minimatch(glob).makeRe();
  if (!regexp) throw new Error(`globに変換できません。glob: "${glob}"`);
  return regexp.toString().slice(1, -1); // 前後に `/` がついてしまうので、sliceする
};

解説

globRegExpに変換する際にちょうど良いライブラリを見つけるのに時間がかかったので、本記事を書きました。

まず glob to regexp などで検索すると glob-to-regexp のようなパッケージが出てきます。NPMでは相当なダウンロード数がありそうですが、レポはpublicアーカイブになっており、このまま利用するのも少し気が引ける状況でした。

そこで、Node.jsglobを使ってファイルを読み込む際の定番ライブラリ glob を見てみたところ、内部的に minimatch というパッケージを利用してパターンマッチさせているとの記述があります。

では、minimatchの方をみてみると、NPMのno内部でglobパターンマッチに利用されており、glob文字列をJSのRegExpオブジェクトに変換できるという旨記載がありました。確かにNPMのレポジトリをみると、package.json に記載されています。

以上から、Node.jsを利用する以上、NPMと同じロジックでglobを扱うのが自然と考えminimatchを利用することにしました。

minimatchの中には makeRe() という関数があり、これで RegExp オブジェクトを吐き出せるようです。

ちなみに、RegExpオブジェクトにはtoString()メソッドが利用できますが、/./.toString() → '/./'のように、前後に / がつくので、.slice(1, -1)でとってあげるようにしないと、RegExp <> string間の相互変換は冪等な操作にならないようです。

以上、小ネタでしたが参考になれば幸いです。