Ruby の素敵なワンライナーコマンド「rb」

つらつらと yhara.jp を見ていたら、sedやawkが覚えられないRubyistのための「rbコマンド」という記事があって大変におもしろかったです。Ruby には -n や -p といったワンライナー用のオプションがあるのですが、自分はこれが覚えられない。sedawk も覚えられないのですが、そんな私のために強い味方があらわれた感じです。

それは Ruby で書かれた rb コマンドというやつ。yhara さんの挙げられている例だと、ps コマンドで PID の部分だけ抜き出す。

$ ps | rb -l split[0]
PID
8123
8203
8204

おお、簡単ですね。Ruby のコードがそのまま書けていて、なるほどよくわかる。これは -l オプションがついているやつですね。

デフォルトだとこんな感じ。僕の Ruby コードたちから、"maze" という文字を含むファイルネームを抜き出してみます(grep を使うといいのだが、まあ例だから)。

$ ls -l | rb 'select {|l| /maze/.match(l)}'
-rw-r--r--  1 tomoki tomoki      2225  7月 25 16:52 3d_maze_generate.rb
-rw-r--r--  1 tomoki tomoki      4237 10月 26 15:08 3d_maze_walk.rb
-rwxrwxrwx  1 tomoki tomoki      3180  4月 19  2018 maze.png
-rwxrwxrwx  1 tomoki tomoki      3086  4月 19  2018 maze.rb
-rwxrwxrwx  1 tomoki tomoki      2919  4月 19  2018 maze1.rb
-rwxrwxrwx  1 tomoki tomoki      1397  4月 19  2018 maze_another.rb
-rwxrwxrwx  1 tomoki tomoki   2629384  4月 19  2018 maze_never_turn_left.gif
-rwxrwxrwx  1 tomoki tomoki      1869  4月 19  2018 maze_never_turn_left.rb
-rwxrwxrwx  1 tomoki tomoki       744  4月 19  2018 maze_never_turn_left.txt
-rwxrwxrwx  1 tomoki tomoki      1348  4月 19  2018 maze_never_turn_left_make_result_png.rb
-rwxrwxrwx  1 tomoki tomoki      1485  4月 19  2018 maze_never_turn_left_result.txt
-rwxrwxrwx  1 tomoki tomoki      1357  4月 19  2018 solve_maze.rb
-rw-rw-r--  1 tomoki tomoki       985 12月 12 11:39 solve_maze1.rb
-rw-r--r--  1 tomoki tomoki       846  7月 12 10:04 test_3d_maze.rb
-rwxrwxrwx  1 tomoki tomoki      2730  4月 19  2018 walk_maze.rb

おお、簡単。でも、どうなっているのだ?

本体はすごくシンプル。
rb

#!/usr/bin/env ruby
File.join(Dir.home, '.rbrc').tap { |f| load f if File.exists?(f) }

def execute(_, code)
  puts _.instance_eval(&code)
rescue Errno::EPIPE
  exit
end

single_line = ARGV.delete('-l')
code = eval("Proc.new { #{ARGV.join(' ')} }")
single_line ? STDIN.each { |l| execute(l.chomp, code) } : execute(STDIN.each_line, code)

これに "rb" という名前をつけて、実行権を与えてパスのとおったところに置くだけ。たった 9行で、すごい。なるほど、よくわかるコードですね。引数で与えられたコードを eval で Proc 化して、instance_eval で実行しているだけ。デフォルトでは Enumerator を返していて、-l オプションだと各行について実行してくれるわけですね。いやあ、これは便利に使わせてもらいます。

なお、第 1 行目('File.join'...)は、'.rbrc' ファイルを設定ファイルにしていて、これがあると先にロードしておくというものです。


もともとの作者のページはこちら。
https://github.com/thisredone/rb
インストール(というほどではないが)がよくわからない人は、作者が全部自動でインストールできるコードを載せてくれてあります(Linux 用)。

$ sudo curl https://raw.githubusercontent.com/thisredone/rb/master/rb -o /usr/local/bin/rb && sudo chmod +x /usr/local/bin/rb