purlの背景と動機
はい、Weekend OSSです。今日はですね、私が作ったpurlというCLIツールの話ができればなと思っています。よろしくお願いします。
よろしくお願いします。では早速、そのpurlを作ることになったきっかけから聞かせてください。
例えば、setやpurlで感じていた、ここが辛いなっていう瞬間、どんな場面だったんでしょうか。
そうですね、よく使われているのがcedoだと思うんですけど、cedoって、僕普段mac使ってるんですけど、
macに入っているcedoってBSDcedoと呼ばれているもので、Linuxに入っているGNUcedoとは違うものなんですね。
なので、同じコマンドなのに微妙に使い方が違うっていうところがまず辛い。これが多分一番実害としてあるところかなと思います。
しかもですね、我々って普段正規表現というと、purlの正規表現、PCREとかって言われるんですけど、そのpurlの正規表現をみんな使ってるんですよね。
普段正規表現といった場合は。けどcedoってpurlの正規表現じゃないんですよね。それより前からあるものなので。
なので微妙に我々が慣れ親しんでいる正規表現とは違うものだっていうところが、ここがすごい辛いポイントで。
なので、僕自身は普段プログラミング言語のpurlを以前はよく使ってました。こういう場面で。
で、なんでpurlがいいかっていうと、我々が慣れ親しんだ正規表現がそのまま使えるっていうところと、
もともとプログラミング言語なので非常に柔軟性が高いっていうところ。
そしてなんといってもポータビリティですね。MacとLinuxで当然同じ挙動をするので、
MacでLinux動かないかもとかそんなこと考える必要がないっていうところが非常に良かったです。
なんですけど、じゃあ最近どうかっていうと、やっぱりpurlってもう最近ほとんど使われてないですし、
あと若い人たちがもう使ってないんですよね。なので今更これを他の人にお勧めするのかっていう問題がまずありましたし、
なんといってもですね、最近入ってないんですよねそもそも。
以前だともうどこでもpurl入ってるよねっていう安心感があったんですけど、
今は意外と入ってなくて、Macもデフォルトだともう入ってないですし、
Linuxも例えばRed Hat系のミニマムなOSだともう入ってないんですよねpurlって。
しかも最近でDockerで使うのが一般的なので、Dockerってやっぱりイメージ小さくしたいっていう権が大きいので、
結構最近のDockerって結構入ってないんですよpurlって。
で、purl入れちゃうとすごい時間もかかっちゃうし、すごいでかくなっちゃうんで、
やっぱり入れる、改めて入れるっていうのも現実的じゃないっていうところ。
で、やっぱりその簡単にインストールはもうバイナリー一個ポンって持ってくるだけで良くて、
で、我々が慣れ親しんだpurlの正規表現が使えて、PCREですね、PCREの正規表現が使えて、
MacとLinuxで同じ使い方ができるっていうような支援ライトツールってないのかなと思って、
これが意外とないんですよね。なんでないんだろう。じゃあ作るかと思って作ったっていうのがきっかけです。
purlの名前の由来とコンセプト
なるほど。そういう背景があったんですね。
確かにBSDセットとGNUセットの違いとか、purlが最近は入ってない環境が増えてるっていうのは実務的な悩みとしてすごくわかります。
つまりpurlはそういう昔はpurlで安心だったけど、今はもうないなら自分で作ろうっていう発想から生まれたわけですね。
ではもう少し掘り下げて、今度は名前の由来について聞いてみましょうか。
purlという名前を選んだ理由、もうちょっと教えてください。
そうですね。ここについてはプログラミング言語のpurlとは全く関係がなくてですね、川のせせらぎみたいなそういったものが由来になってます。
川で流れるように、文字列とかを川の流れのようにどんどん整形できるっていうようなイメージでつけられた名前で、すごく綺麗なので個人的には気に入ってますね。
なるほど。purlとは全く関係なく川のせせらぎから似てるわけですね。文字列を流れるように整形していくっていうイメージ、確かに名前からしてとても綺麗でわかりやすいです。
じゃあその名前の由来がわかったところで、purlの基本的なコンセプト、特に簡単にバイナリーで動くとかMacとLinuxで同じ動きをするっていう部分について、もう少し詳しく教えてもらえますか。
そうですね。Goで、PureGoで作ってます。積極表現はGoのregexpに全部丸投げするっていう方針で作られています。
なのでGoの積極表現で使える記号は全部使えます。Goなので、バイナリー1個持っていけばどこでも使えるっていう風な設計になっています。
なるほど。GoでPureGoとして作ってるから、Goのregexpがそのまま全部使えるし、バイナリー1個あればどこでも同じように動くっていう設計なんですね。
シンプルでわかりやすいですし、まさに流れるように使えるっていうイメージにあってますね。
purlの設計と機能
関連する話として、purlに用意したオプション設計、特にフィルターやエクスクルードを複数回使えるようにした理由って何かありますか。
そうですね。パイプして複数個渡すってグレップとかでも僕はよくやると思うんですけど、僕自身はよくやるんですけど、グレップでパイプしちゃうと当然なんですけど&条件になって、両方ともヒットしないと出てこないっていう風になるんですよね。
そうじゃなくて、複数書いて、どれかにヒットしたら出てくるみたいなことをやりたいケースがあるなと思ったので、それでフィルターを複数渡せるような設計にしました。
もちろん赤表現が使えるので、ORで赤表現書けばいいんですけど、もうちょっと手軽に使えた方がいいなと思っていて、自分が手元で触ってて、これ使えた方がいいなっていうので、複数OR条件でどんどん繋げられるっていうのを作りました。
なるほど。つまりパイプで何度も繋ぐ代わりに、フィルターに複数書いてOR条件的に使えるようにしたんですね。確かにその方が直感的で扱いやすいし、手軽さが増しますね。
では話題をもう少し広げて、LINEモードやファイル一括読み込みモードについても聞いてみましょうか。なぜ標準入力は待たずに流すようにしたのか、そのあたりの設計意図も教えてください。
そうですね、これすごい悩んだんですよね。例えばアクセスログとかでリクエストが来たらどんどん追加されるじゃないですか。なのでアクセスログとかでパイプしてグレップするとかって僕はよくやるんですよね、そういったこと。
そういうのをやると、アクセスログって一行一行が別々のコンテンツだし、ガーッとどんどん書き込みがされるので、パールも同様にアクセスログが書き込みされたらガーッと出てきてほしいと思ってました。
なんですけど、表示するには正規表現が実行が終わってないと出せないんですよね、パール側は。なので正規表現をどの単位で実行して表示するかっていう問題があって、なのでパールだと標準入力をパイプで渡された場合は自動的にLINEモードになってアクセスログとかそういうのが渡されているっていう想定になります。
なので、それで一行一行を見ていって、その正規表現が通ったらもう拒否出力するっていうような設計になってます。これによって、なんていうんだろうな、手軽に使えるようになっている。
で、毎回全部がそうなってない理由としては、そのパイル全体を見て、例えばその前の行がこうなっていたら後ろの行でこうするみたいな、そういうことをやりたい場合は一行一行を見るんじゃなくて、その全体を見ないといけないので、その全体を見て出す、みたいな挙動にしないといけないので、なのでファイルを渡された場合は全体を見て正規表現を実行しているし、標準入力でパイプだとされた場合は一行一行を見て正規表現を実行して出す。
実行して出しているっていう挙動の差があります。ここはどうするのか正しいのか未だによく分かってないんですけど、僕が使っている限りは一番しっくりくるかなと思ってます。
なるほど。つまりアクセスログみたいに流れてくる入力をリアルタイムに処理したいときは、一行ごとに正規表現をかけてすぐダメるようにしているわけですね。
一方でファイル全体を見る場合は、ファイル全体を一度処理してから出力する。すごく理にかなってますし、実際に使うときの柔軟性を意識している感じが伝わってきます。
じゃあ関連する話として、パールのオプション設計、特にフィルターやエクスクルードを複数回使えるようにした理由ももう少し教えてください。
そうですね。僕が手元で使っていて、なんでこれできないんだろうとか、実際に使っていていろいろ不満が溜まったので、そういう機能に最初からしていたというところですね。
purlのユースケース
なるほど。実際に使っている中でこうできたらいいのにという不満を解消する形で最初からオプションを柔軟にしたわけですね。確かにそういう使い手目線でも工夫が詰まっているとより便利になりそうです。
じゃあ話題をつなげて、パールを実際に使うユースケースやどんな場面で特に役立つかという例もぜひ聞かせてください。
そうですね。例えばソースコードの中でこの文字列を全部これに置換したいみたいなときは、僕がお勧めしているのはGitGrepと組み合わせる方法で、
GitGrep-Lでグレップした文字列を渡すと、その文字列がヒットするファイルのリストが出てくるので、それをパイプしてXargusでパールを呼び出すと、そのパールに一個一個ファイルを渡してきます。
パールには-overwriteというオプションがあるので、その-overwriteで-replaceというオプションで置換することができるので、それですべてのファイルの置換がGoのregexpで、我々が慣れたregexpでちゃんと書けるというような使い方だったりとか、
あとさっき言ったアクセスログで特定のパターンのところだけ出力してみたいよとか、逆に特定のパターン除外してみたいよみたいな、グレップだとGrep-vで使えるんですけど、パールだと-excludeという名前になってます。それで使える。
グレップと同様に、-filterの方だとそのヒットしたところは色が変わったりするので、これが出たんだみたいなのがすぐ分かるようになっています。
なるほど。具体的なユースケースとしてGit-Grepと組み合わせて一括で時間をかけたり、ログの特定パターンをフィルターしたり、除外したりするのが簡単になるわけですね。しかも色が付くから、結果もすぐ就任できると。
とても実用力で、現場で役立つイメージが湧きました。ではさらに関連する話題として、デモ道具を作ったときの裏側や見せ方の工夫なんかも、もしあれば教えてください。
そうですね。やっぱりこういうPerlみたいなシェーライトツールって実際に使ってもらうまでのハードルが高いと思っていて、なのでGitHubのリドミュー上に動画ファイルがいくつか見れるようになってます。それで実際に使ったイメージっていうのを掴んでもらえるようになっています。
正直使い方としては、GrepとかPerlとかCedoとかそういったものを使ったことがある方だったら、そんなに違和感なく使えるかなと思っていて、むしろオプション名が結構明確になっているので、その点も慣れてもらえれば結構一番しっくりくるんじゃないかなと思っていたりします。
なるほど。確かにシェーライトツールって最初に手を動かしてもらうまでがハードルですもんね。GitHubのリドミューに動画を載せて実際の使用感を見せる工夫はとても親切だと思います。オプション名もわかりやすいとのことなので、GrepやPerlに慣れてる人なら自然に使えそうですね。では、こういった工夫を踏まえて今後Perlをどう進化させていきたいか、ちょっと未来の伝導も聞いてみましょうか。
そうですね。僕自身が結構使っているので、あれなんか変だなと思ったら、ちゃんと直してます。なので、そういったところ気軽に使えるようなツールにどんどんしていきたいなと思ってますし、実際僕は業務でも使ったりしていて、
シェルスクリプトの中で正規表現を使った結果を出力したりとか、このファイルの中でこの文字列だけ抜き出したりとか、そういうのって僕自身は結構あって、そういう時にPerlを使ってさくっと正規表現で取得してくるっていうことに使ってます。
例えばGitHub Actionsとかで使いたいって場合も、一応コピペで対応できるようなものを用意しているので、そのGitHub上にリリースファイルでバイナリー配布しているので、それをダウンロードしてUserLocalBinとかに置いておけばPerl使えますので、結構気軽に使えるような工夫っていうのはいくつかしてますね。
なので、ぜひ使ってほしいと思ってますし、使った時にちゃんと役に立つようなツールにもっともっとしていきたいなと思ってます。
なるほど。つまり、自分でも業務でどんどん使いながら改善して気軽に導入しやすくなるよう工夫を重ねてるわけですね。
GitHub Actionsでコピペで使えるような例も用意して、バイナリーを簡単に配布してるから、どんどん気軽に使ってほしいという感じですね。
では最後にもう一つだけ関連する話題を広げると、Perlをチーム内で共有するとき、どんなふうに紹介すると使いやすいとか、そういうポイントからでも教えてください。
まあそうですね。
REG EXPというか、正規表現でPCREの正規表現を使いたくないとか、あとLinuxとMacで挙動が微妙に違うの嫌じゃないとか、そういう説明でいいのかなと思っていて、
あとGitHub Actionsとかで気軽に使えるようになってるので、実際にGitHub Actionsで使ってみるとか、そういった実際に入れてみて正規表現を書けるんだみたいな形で、
普通にGoの正規表現に丸々渡してるだけなので、特別な機構とか覚える必要って全くないんですよね。
なのでその辺りはとっつきやすいんじゃないかなと思っていたりします。
なるほど。要するにPCREが使いたいけど、MacとLinuxで挙動が違うのは面倒だよね、とかGitHub Actionsで簡単に正規表現を使いたいよね、みたいなポイントで紹介するとチームにもすっと受け入れられそうですね。
特別な仕組みを覚える必要がないというのは、まさに導入しやすさの大きなポイントですね。
というわけで、今日はパールの誕生のきっかけから、名前の由来、基本的な設計思想、そして実際の使い方までいろいろお話を伺えてとても面白かったです。
まだまだ聞きたいことはたくさんありますが、また次の話題につなげていきましょう。
はい、ありがとうございました。