Rustでgrepの検索結果の周囲を表示するコマンド suln を作ってみた
grepの検索結果の続きを表示したくなったので専用のツールをRustで作ってみた めちゃくちゃニッチなツールだとは思う
https://gyazo.com/493e944f3ec0c3c07d08f272c1c5a8ed
作ったもの
clates.io にも登録したので cargo でインストールできる
インストール方法はリポジトリのREADMEを参照
名前はいつも適当に決めていて「surroundings of line number」から文字を4つ拾ってsulnにした
発音は僕も分かってなくて、たぶん「サルン」になると思う
できること
grepで検索をした時に、ファイル名と行番号を表示できる code:sh
⟩ grep -Hn '###' README.md
README.md:62:### Usecase: searching JSON data
README.md:133:### Pre-requisite
README.md:137:### Build
README.md:143:### Test
-B -A -Cで検索結果の前後の行を表示できる
-A は後ろの行を追加で表示する
code:sh
⟩ grep -Hn -A 2 '###' README.md
README.md:62:### Usecase: searching JSON data
README.md-63-
README.md-64-Here is an example of AND search for multiple keys in JSON.
--
README.md:133:### Pre-requisite
README.md-134-
README.md-135-* rustc 1.64.0 (a55dd71d5 2022-09-19)
この検索結果にgrepを重ねると、いわゆるAND条件での検索になるが、当然前後の行データは失われる
code:sh
⟩ grep -Hn -A 2 '###' README.md | grep rustc
README.md-135-* rustc 1.64.0 (a55dd71d5 2022-09-19)
そこで、このAND検索後の出力に対してsulnを付け足すことで、その前後の行データを表示できる code:sh
⟩ grep -Hn -A 2 '###' README.md | grep rustc | suln -B 2
README.md:133:### Pre-requisite
README.md:134:
README.md:135:* rustc 1.64.0 (a55dd71d5 2022-09-19)
sulnのオプションは-B -A -Cのみ。これはgrepのオプションと同じ名前で、同じように振る舞う 今回の例だと以下のようにgrepだけでも同じことができるが、違いはgrepが表示していない場所でも表示できること
code:sh
⟩ grep -Hn -A 2 -m 2 '###' README.md | grep -B 2 rustc
README.md:135:### Pre-requisite
README.md-136-
README.md-137-* rustc 1.64.0 (a55dd71d5 2022-09-19)
こんな感じで連結しまくれる
code:sh
⟩ grep -Hn -A 2 -m 2 '###' README.md | grep Pre
README.md:135:### Pre-requisite
⟩ grep -Hn -A 2 -m 2 '###' README.md | grep Pre | suln -A 1
README.md:135:### Pre-requisite
README.md:136:
⟩ grep -Hn -A 2 -m 2 '###' README.md | grep Pre | suln -A 1 | suln -A 1
README.md:135:### Pre-requisite
README.md:136:
README.md:137:* rustc 1.64.0 (a55dd71d5 2022-09-19)
⟩ grep -Hn -A 2 -m 2 '###' README.md | grep Pre | suln -A 1 | suln -A 1 | suln -A 2
README.md:135:### Pre-requisite
README.md:136:
README.md:137:* rustc 1.64.0 (a55dd71d5 2022-09-19)
README.md:138:
README.md:139:### Build
それだけ
背景
grepの結果の続きを表示するのをパイプつなぐだけで簡単に表示したいなぁと思ったから awkとか使ってゴニョゴニョやれば同じことを実現できると思うけれど、ちょい面倒 sulnが役に立つシーンはめちゃくちゃ限定的だと思うけれど、局所的に役に立つと思う 経験則的に、勉強するなら何かツールを作る時に使うのが一番身に付くので、何かツール作る機会を探していた
たまたま今回のニーズを思いついて、せっかくなのでRustで実装してみるか、となった 感想
超久しぶりにRustを勉強し直したので、ほとんど覚えていなかった teipに改修を入れるMRを出したのが2022年なので、今から2年も前になる それから全くRust書いてなかったので、完全に忘れてしまっていた まぁその時も必要な領域の勉強しかしてなかったので、ほとんど理解してなかったような気もするが
パフォーマンス計測とかはしていないので、実際早いのか、とか省メモリなのか、とかは分からない
コンパイラにバチボコに怒られまくったけれど、一通り作り終えて見ると所有権と借用についてはある程度分かった気がする
後面白かったのはResult型とOption型をunwrapできることやmatchの結果を変数に代入できること
パターンマッチングが強力で便利そうだった
イテレータ用のメソッドが充実しているのも良かった
ファイルを開いても変数がdropされる時にファイルをクローズしてくれるのも良いね
Files are automatically closed when they go out of scope. Errors detected on closing are ignored by the implementation of Drop. Use the method sync_all if these errors must be manually handled.
少なくとも、この程度のツールを実装するのに土日を半日ずつ使う程度で済んだ
11時間程度かかった
https://gyazo.com/a8a717b2636a470c2dbbd59ea9ff0aca
正規表現やCLI用のライブラリが標準に含まれてなかったのには困惑したが
書いてみて結構楽しかったけれど、やっぱりGoのが好みなのでしばらく書くことは無いと思う