Rubyでコマンドを作ろう！

TECH::CAMPアドベントカレンダー３日目です！
元iOSメンターでRuby歴４ヶ月の井上が頑張ってRubyの記事を書きます！[^1]
今日ご紹介する内容は「Rubyでコマンドを作ろう！」です！
~~「シェルスクリプト使えよ！」とか言わないで。~~

##実行環境
実行環境は以下の通りです。
macOS 10.12.1
Terminal.app 2.7.1
ruby 2.3.1p112

##引数を取得しよう
コマンドである以上はターミナルからコマンドライン引数を取得することは必須ですので、今からそのやり方を紹介します。

RubyのObjectクラスには`ARGV`という定数が存在します。
この`ARGV`はRubyスクリプトに与えられた引数を表す配列です。
この配列の中身を参照することでコマンドライン引数を取得できます。

また、Kernelモジュール[^2]には`$0`と`$PROGRAM_NAME`という特殊変数が存在します。
これらはどちらも現在実行中のRubyスクリプトの名前を表す文字列です。

以下はこれらを使って実行中のプログラムのファイル名とそれに与えられた引数を表示するプログラムです。

```rb:MyCommand.rb
puts "PROGRAM_NAME：#{$PROGRAM_NAME}"
ARGV.each_with_index do |arg, i|
    puts "ARGV[#{i}]：#{arg}"
end
```

```bash:実行例
$ ruby MyCommand.rb aaa bbb
PROGRAM_NAME：MyCommand.rb
ARGV[0]：aaa
ARGV[1]：bbb
```

## プログラムから他のコマンドを実行してみよう
Rubyプログラム中から他のコマンドを実行する方法は４つあります。

### system( command )
子プロセス(サブシェル)を生成して、引数として与えた文字列をコマンドとして実行します。
コマンドの出力を得る必要がなく、単にコマンドを実行したいだけの場合はこちらを使うと良いでしょう。

```rb:MyCommand.rb
system("echo 'hi'")
```

```bash:実行例
$ ruby MyCommand.rb
hi
```

### exec( command )
引数で指定されたコマンドを実行します。なお、引数で指定されたコマンドのプロセスID(PID)はその実行したプログラムのプロセスID(あるいは shellのプロセスID)になります。
**つまり、`exec()`を使用するとその時点で現在実行中のプログラム自身が起動させたコマンドに置き換わりますので、コマンドの起動に成功した場合はこのメソッドからは戻りません。**


```rb:MyCommand.rb
exec("echo 'hi'")

p "exec実行後"  #通常なら実行されない
```

```bash:実行例
$ ruby MyCommand.rb
hi
```

### \`(バッククォート)で囲む
実行したいコマンドを \`(バッククォート)で囲むと囲まれた文字列を外部コマンドとして実行し、その標準出力を文字列として返します。
コマンドの出力を得たい場合はこちらを利用すると良いでしょう。

```rb:MyCommand.rb
p `echo 'hi'`
```

```bash:実行例
$ ruby MyCommand.rb
"hi\n"
```

### %記法 ( %x( command ) )
%x( 実行したいコマンド )とすることで \`(バッククォート)で囲んだ場合と同じ動作を行います。

```rb:MyCommand.rb
p %x(echo 'hi')
```

```bash:実行例
$ ruby MyCommand.rb
"hi\n"
```

これらの機能とmacOSで標準インストールされているコマンド「open」を使ってGitHubをSafariで開くプログラムが以下になります。

```rb:MyCommand.rb
exec("open -a safari https://github.com/")
```

たった一行だけのコードですが、これだけでGitHubを開く事ができます。
~~openコマンドは最高だぜ！！~~

```bash:実行例
$ ruby MyCommand.rb
#実行するとSafariでGitHubのページが開く
```

#作ったプログラムをコマンドみたいに使えるようにしよう
これでコマンドを作る事ができるようになりましたが、このままだと実行するのが面倒です。
なので、エイリアスを設定することでコマンドっぽく使えるようにしましょう。

ターミナルにおけるエイリアスとは、コマンドの入力を省略するための機能です。
よくあるのが`$ ls -l`を頻繁に実行するので`ls -l`を`ll`と省略したい時に使います。

ログインしているユーザのみ使えるようにする場合[^3]、`~/.bash_profile`の末尾に
`alias エイリアス名='実行するコマンド'`を追記します。
例えば上記の`ls -l`を`ll`と省略する場合は以下を`.bash_profile`の末尾に追加します。

```text:.bash_profile
#末尾に追記
alias ll='ls -l'
```

保存したらターミナルを再起動するか`$ source ~/.bash_profile`を実行しましょう。
実行するとエイリアスの設定が読み込まれますので、実際に`ll`を試してみましょう。

```bash:実行例
$ ll
#カレントディレクトリの内容が表示される
```

それでは実際にRubyプログラムを実行するためのエイリアスを設定してみましょう。
以下の`gsrch.rb`を`~/bin`に配置しましょう。
(自作コマンドは所定の場所にまとめておくと良いでしょう。)

```rb:gsrch.rb
query = ""

ARGV.each do |word|
  query += "#{word}+"
end
query = query.chop

exec("open http://google.co.jp/search?q=#{query}")
```

次にエイリアスを設定します。
`~/.bash_profile`を開いて末尾に以下を追記します。

```text:.bash_profile
#末尾に追記
alias gsrch='ruby ~/bin/gsrch.rb'
```

保存したらターミナルを再起動するか`$ source ~/.bash_profile`を実行しましょう。
その後、以下を実行してみましょう。

```bash:実行例
$ gsrch まつもと ruby
#実行すると「まつもと ruby」でGoogle検索される
```

##おわりに
いかがでしたでしょうか？
これで皆さんのコンピュータライフが少しでも素敵なものになれば幸いです。

[^1]: 本当はクリスマスも近いので**C言語のCはChristのC（大嘘）**とか言ってC言語の紹介記事でも書こうかと思ったが誰も幸せになるイメージができなかったので辞めた。
[^2]: 全てのクラスから参照できるメソッドを定義しているモジュール。
[^3]: コンピュータ上のすべてのユーザが使えるようにする場合は.bashrcファイルに追記することで利用できる。（参考：http://qiita.com/yutat93/items/b5bb9c0366f21bcbea62 ）