Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

Rubyでコマンドライン操作をレベルアップさせる方法

コマンドラインを本当にマスターするには、数十、場合によっては数百もの小さなユーティリティプログラムを使いこなす必要があります。それぞれが微妙に異なる動作をするため、最初は圧倒されてしまうことも少なくありません。

幸いなことに、こうした単一目的のツールの多くは、Rubyのような汎用プログラミング言語に置き換えることができます。すでにあるRubyの知識をそのまま活かして、コマンドラインスキルを一段引き上げられるのです。

この記事では、Rubyを「コマンドラインのスイスアーミーナイフ」として使うための基礎を解説します。小手先のワンライナーを大量に並べるのではなく、仕組みそのものを理解してもらい、読者自身の問題解決に応用できるようになることを目指します。

コマンドラインからRubyを使う

次のようにしてコマンドラインからRubyプログラムを実行できることは、皆さんご存じでしょう。

$ ruby myprogram.rb

しかし、パイプ経由でコードを渡して実行できることはご存じでしたか?

$ echo "puts 2+2" | ruby
4

さらに便利なのが、コードをコマンドライン引数として直接渡せる機能です。本記事では、この方法を中心に掘り下げていきます。

$ ruby -e 'puts 2+2'
4

初心者の方へ

上記の例が少し分かりにくいと感じましたか?それはパイプやリダイレクトに慣れていないせいかもしれません。まずは入門記事で基本を押さえておくと安心です。以降のセクションではパイプを頻繁に使用します。

入力の扱い方

ほとんどのコマンドラインツールは、「データを受け取る → 処理する → 結果を出力する」という流れで動作します。

入力を取得する方法としては、コマンドライン引数STDINの2つの選択肢があります。それぞれ順番に見ていきましょう。

コマンドライン引数

スクリプトには好きなだけコマンドライン引数を渡せます。コードの後ろに続けて記述するだけです。

$ ruby -e '<your code here>' arg1 arg2 arg3 etc

渡された引数はARGV配列に格納されます。以下の例では配列全体を出力して、中身を確認しています。

$ ruby -e 'puts ARGV.inspect' apples bananas pears oranges
["apples", "bananas", "pears", "oranges"]

注目すべきは、これはRubyが普段から同じように動作しているという点です。コマンドラインを使っているからといって、特別な魔法が働いているわけではありません。詳細についてはARGVに関する記事も参考にしてください。

ちょっとした実用例

少し想像力を働かせてみましょう。自分の名前がウェブ上で何回言及されているかを把握したいとします。ここまで学んだテクニックを使えば、任意のWebページに対してこれを計算するワンライナーを簡単に書けます。

$ ruby -e "require 'open-uri'; puts open(ARGV.first).read.scan(/starr/i).count" <url here>

STDIN

コマンドライン引数は便利ですが、短い値にしか向いていません。例えば『白鯨』の全文を引数として渡したいとは思わないでしょう。そんな大量のデータには、STDINを使います。

STDINに馴染みがなくても心配はいりません。ここでの用途においては、読み込み用に開かれた普通のファイルと同じように扱えます。

具体的にはこういうことです。以下の例では、テキストをパイプでRubyに渡し、RubyスクリプトがそれをSTDINから読み取って画面に出力しています。

echo "bananas!" | ruby -e "puts STDIN.read"
bananas!

catと組み合わせれば、より大量のデータも簡単に入力できます。次の例では、あらゆるファイルオブジェクトで利用可能なfirstメソッドを使って、テキストの冒頭数行を取得しています。

cat moby.txt | ruby -e "puts STDIN.first(3)"
Call me Ishmael. Some years ago--never mind how long precisely--having
little or no money in my purse, and nothing particular to interest me on
shore, I thought I would sail about a little and see the watery part of

ちょっとした実用例(その2)

STDINの使い方がわかったところで、先ほどの例を書き直してみましょう。Webページの取得はcurlに任せて、Rubyはパターンマッチング専用に使います。役割分担が明確になり、より実用的な構成になりますね。

curl <MY URL> | ruby -e "puts STDIN.read.scan(/starr/i).size"

シンタックスシュガー付きSTDIN!

STDINを扱うときは、入力の各行を順番に処理するループを書くことが非常に多いものです。例えば、ディレクトリ内のすべてのファイルの拡張子を取得したいとしましょう。通常のSTDINループを使うと、次のように書けます。

ls | ruby -e 'STDIN.each_line { |l| puts l.split(".").last }'
rb
rb
csv

このSTDINループはあまりにも頻繁に使われるため、Rubyは省略記法を用意しています。-nフラグを付けてスクリプトを実行すると、Rubyが自動的にSTDINの各行をループ処理してくれます。現在処理中の行は、グローバル変数$_に格納されます。

したがって、先ほどの例は次のように書き換えられます。

ls | ruby -n -e 'puts $_.split(".").last'

省略記法を使うかどうかは好みの問題です。コード量は確実に減りますが、その反面、-n$_といった暗記が必要な約束事が増えるというトレードオフもあります。

出力の扱い方

このような場面では、出力をSTDOUTに書き込むのが一般的です。STDOUTを使えば最大限の柔軟性が得られ、出力を別のプログラムにパイプしたり、必要に応じてファイルへリダイレクトしたりできます。

嬉しいことに、いつも使っているおなじみの出力メソッドがそのまま利用できます。ただし一つ注意点があります。putsは自動的に改行を追加します。それが望ましい場合もあれば、望ましくない場合もあるので、状況に応じて使い分けましょう。

puts "hello world"  # STDOUTに "hello world\n" を送る
print "hello world" # 改行を追加しない

すべてを組み合わせる

最後に、実践的な例を見てみましょう。Honeybadgerはアメリカのワシントン州に拠点を置いています。そのため、ワシントン州在住の有料顧客一人ひとりに対して売上税を支払う義務があります。

かなり単純化していますが、基本的には年間の全取引を記録したCSVファイルを保有しており、次のような形式になっています。

1/1/2015,100.00,WA
1/1/2015,50.00,NY

ワシントン州の全取引の合計額を素早く算出するには、次のようなワンライナーが使えます。

$ cat cc.csv | ruby -e 'puts STDIN.inject(0) { |sum, x| date, amount, state = x.split(","); state.strip == "WA" ? sum + amount.to_f : sum }'

もちろん、これはCSVを解析する方法としてはかなり雑なやり方です。このコードをそのまま本番環境に投入することは決してありません。しかし、一回性の問題を解決するための小さなスクリプトを書く楽しさの一つは、細かいエッジケースをすべて無視できる点にあります。今回はあえてそうしている、というわけです。

  1. Rubyでパーサーを自作する方法!StringScannerを使った実装手順を徹底解説

    パース(構文解析)とは、文字列の集まりから意味を読み取り、プログラムが扱える形のデータへと変換する技術です。正規表現でも文字列の解析は可能ですが、すべての場面に適しているわけではありません。 たとえば、正規表現でHTMLを解析するのはあまり良い方法ではないというのは、プログラミング界隈ではよく知られた話です。 Rubyにはnokogiriという強力なライブラリがあり、HTMLの解析はこれに任せられます。しかし、自分でパーサーを一から作ってみると、文字列処理や構文解析の仕組みについて多くのことを学べます。それでは早速始めていきましょう! Rubyでのパースの基本:StringScannerクラス

  2. ID Watchdog(アイディーウォッチドッグ)徹底解説|個人情報を守るID保護サービスのすべて

    ID Watchdogとは ID Watchdogは、13年以上にわたり市場で確かな実績を積み重ね、なりすまし(ID盗難)被害を徹底的に防いできた個人情報保護サービスです。2005年6月、クレイグ・ラムゼイ(Craig Ramsay)氏がクレジット業界の専門家たちとともにコロラド州デンバーで創業し、現在では米国のID盗難対策サービス分野におけるトップ5企業に名を連ねています。 創業当初の2年間、同社は法執行機関、銀行、クレジット会社、司法関係者、情報プライバシーの専門家らとのコンサルティングに注力。その後2007年には、個人向けサービス、保険パートナー向けサービス、従業員福利厚生、民間医療交換