Rubyによるワンライナーのまとめ

Rubyでワンライナーを書く際によく使うコマンドライン引数と具体例をまとめてみた.

基本

-e : コマンドラインからスクリプトを指定

コマンドラインからスクリプトを指定する場合に使う.ワンライナーでは必須.

$ ruby -e 'puts "Hello, world!"'

行単位の処理

-n : 各行ごとに処理

プログラム全体が以下のwhileで囲まれているように動作する.

while gets
  ...
end

標準入力やファイルの各行に対して処理を行いたい場合に便利.getsの結果は$_に格納される.

$ ruby -ne 'puts $_ if $_.include?("mickey24")' foo.txt
-p : 各行ごとに処理&出力

-nとほぼ同様だが,各ループの最後で

print $_

が実行されるようになる.標準入力の各行に対して処理を行いつつ出力していく場合に便利.

$ ruby -pe '$_.upcase!' foo.txt
-l : 入力&出力の改行文字の自動処理

以下の2つの効果がある.

  1. $\が$/と同じ値になる.つまりprintの出力結果の末尾にgetsの行区切り文字(デフォルトは改行文字"\n")が付くようになる
  2. -nや-pがセットされている場合,getsで読み込まれた各行に対してString#chop!が呼び出される

getsで読み込んだ$_の末尾に"\n"が付いてほしくない時や,-pで出力される文字列に自動的に"\n"を付けてほしい時に使うとよさげ.

-a : オートスプリットモード

-nや-pと組み合わせて使う.オートスプリットモードがオンになり,各ループの先頭で

$F = $_.split

が実行されるようになる.

$ ruby -aple '$_ = $F.join(",")' foo.tsv

-aを使う場合は-lも組み合わせて使う方がいいだろう(-lがないとsplit結果の最後の要素にだけ改行文字が付いてしまう).

-Fregexp : splitの区切り文字の変更

入力フィールドセパレータ($;)にregexpを代入し,splitでデフォルトで使われる区切り文字を変更する.-aと組み合わせると便利.

$ ruby -F, -aple '$_ = "#{$F[0]}, #{$F[2]]}"' foo.csv

その他

-r feature : require

スクリプト実行前にfeatureをrequireする.

$ ruby -r base64 -e 'puts Base64.encode64("mickey24")'
-Kc : エンコーディングの設定

外部エンコーディングとスクリプトエンコーディングを設定する.指定できるエンコーディングは以下の通り.

  • -Ke : EUC-JP
  • -Ks : Windows-31J, CP932
  • -Ku : UTF-8
  • -Kn : ASCII-8BIT, BINARY
$ ruby -Ku -e 'puts "うさみみ"'
-i[extension] : 入力ファイルの上書き

入力ファイルを出力結果で上書きする.

$ ruby -i -pe '$_.gsub!("\r\n", "\n")' foo.txt

元のファイルを残しておく場合は-iの直後に拡張子を指定する.以下の場合は元のファイルがfoo.txt.bakとして保持される.

$ ruby -i.bak -pe '$_.gsub!("\r\n", "\n")' foo.txt

コマンドライン引数まとめ

-eコマンドラインからスクリプトを指定
-n各行ごとに処理
-p各行ごとに処理&出力
-l入力&出力の改行文字の自動処理
-aオートスプリットモード
-Fsplitの区切り文字の変更
-rrequire
-Kエンコーディングの設定
-i入力ファイルの上書き

具体例

foo.txtの各行に行番号を付けて標準出力に出力する.

$ ruby -ne '$l ||= 1; puts "#{$l}: #{$_}"; $l += 1' foo.txt

foo.txtの各行の"\r\n"を"\n"に置き換え,foo.txtを上書きする.

$ ruby -i -pe '$_.gsub!("\r\n", "\n")' foo.txt

ユーザ"mickey24"が保持するプロセスのIDを標準出力に出力する.

$ ps aux | ruby -anle 'puts $F[1] if $F[0] == "mickey24"'

カンマ区切りのfoo.csvの3列目が24以上の行のみ標準出力に出力する.

$ ruby -F, -anle 'puts $_ if $F[2].to_i >= 24' foo.tsv

以上

-n,-p,-aあたりが使えるようになると劇的にワンライナーを書きやすくなるので,是非マスターしておきたい.

ここで挙げたRubyのコマンドライン引数はPerlのそれとほぼ同じなので,これらのことを覚えておけばPerlでもワンライナーが書けるようになると思う.