Ruby入門

Rubyを使うといっても、本ブログではそこまで本格的にということではなく、あくまでもコマンドラインでパイプをつなげて組み立てるrubyコマンドとして使います。

Ruby インストール

インストールは、apt-get install ruby等で。

takk@deb9:~$ ruby --version
ruby 2.3.3p222 (2016-11-21) [x86_64-linux-gnu]
takk@deb9:~$

私の環境ではバージョン2.3.3でした。

Rubyで私が一番好きなところは、さくっと試せるってところです。
インタラクティブモードを備えてます。irbコマンドを実行するだけです。

takk@deb9:~$ irb
irb(main):001:0>


では、Hello Worldです。

irb(main):001:0> print "Hello World!"
Hello World!=> nil
irb(main):002:0>

はい。表示されましたね。
Hello World!と表示されたのは良いのですが、それに続く、nilとは何でしょうか。

ここで関数(メソッド)を定義してみましょう。関数を作るには、def 名称で始めて、endで終わります。 
空関数を作ってみます

irb(main):002:0> def aaa()
irb(main):003:1> end
=> :aaa
irb(main):004:0>

aaaという名前を付けました。これを実行してみます。

irb(main):004:0> aaa
=> nil
irb(main):005:0>

=> に続いてnilが表示されました。

次にaaaに戻り値を設定して実行してみます。

irb(main):005:0> def aaa()
irb(main):006:1> return "HELLO"
irb(main):007:1> end
=> :aaa
irb(main):008:0> aaa
=> "HELLO"
irb(main):009:0>

=> に続いてaaaの戻り値として設定した”HELLO”が表示されました。

先ほど戻り値を設定していなかった関数aaaでは、nilが表示されました。つまりnilとは何も値を戻してないってことです。
冒頭の表示はHello World!に改行がなくわかりづらかったのですが、改行を入れるとこうなります。

irb(main):009:0> print "Hello World!\n"
Hello World!
=> nil
irb(main):010:0>

実行後の一行目ではHello World!という表示結果、それに続いてnilが表示されていますね。つまり、printの戻り値です。

irbを抜けるには、quitを実行します。

irb(main):010:0> quit
takk@deb9:~$

Ruby 変数

Perlの変数(スカラー)は頭に$がついてました。Rubyの変数も同じように$をつけることができます。Perlでは$はスカラー変数を表していましたが、Rubyではグローバル変数を表します。ローカル変数の場合は、$をつけません。

takk@deb9:~$ irb
irb(main):001:0> $a="GLOBAL"
=> "GLOBAL"
irb(main):002:0> b="local"
=> "local"
irb(main):003:0> def aaa()
irb(main):004:1>  puts $a
irb(main):005:1>  puts b
irb(main):006:1> end
=> :aaa
irb(main):007:0> aaa
GLOBAL
NameError: undefined local variable or method `b' for main:Object
        from (irb):5:in `aaa'
        from (irb):7
        from /usr/bin/irb:11:in `<main>'
irb(main):008:0>

このように、$aはグローバル変数なので、aaaの中で参照できますが、bは、ローカル変数のため、aaa内から参照できません。
コマンドラインで使う分には、ほとんどローカル変数で事足りますので、$をつけないことになります。$がないと変数名が短くなるわけですので特な気がしますが、Perlでやっていたこんな表現ができなくなります。

takk@deb9:~$ perl -e '$a="HELLO"; print "$a $a\n"'
HELLO HELLO
takk@deb9:~$

Rubyで同じことをすると、当然なんですが文字列がそのまま表示されます。

takk@deb9:~$ ruby -e 'a="HELLO"; print "a a\n"'
a a
takk@deb9:~$

変数の中身を表示するには、こう書くことになります。

takk@deb9:~$ ruby -e 'a="HELLO"; puts a+" "+a'
HELLO HELLO
takk@deb9:~$

Rubyの変数は、インスタンス、クラス変数がありますが、コマンドラインで使う予定がないので覚えてません。Rubyはオブジェクト指向ですので、変数もオブジェクトです。

takk@deb9:~$ irb
irb(main):001:0> a="123"
=> "123"
irb(main):002:0>

今、文字列”123″をaに格納しました。aに1を足してみます。

irb(main):002:0> a + 1
TypeError: no implicit conversion of Fixnum into String
        from (irb):2:in `+'
        from (irb):2
        from /usr/bin/irb:11:in `<main>'
irb(main):003:0>

エラーになりました。文字列に数値の1を足したので当然ですね。Perlの方が特殊なのかもしれません。
aを数値として解釈するには、数値に変換するメソッドを使えばよいです。

irb(main):003:0> a.to_i + 1
=> 124
irb(main):004:0>

頼もしいですね。オブジェクトなので、メソッドを使えば何でもできる気がしますね。

Ruby 配列

Ruby続きです。配列は、全体を[]で囲って要素を,(カンマ)で区切れば作成できます。

irb(main):001:0> a = [10,20,30,40]
=> [10, 20, 30, 40]
irb(main):002:0> 

要素へアクセスするには、0始まりのインデックスを指定します。

irb(main):002:0> a[3]
=> 40
irb(main):003:0>

クォートで囲まれた要素であれば、文字列の配列となります。

irb(main):003:0> a = ["aaa","bbb","ccc","ddd"]
=> ["aaa", "bbb", "ccc", "ddd"]
irb(main):004:0> a[1]
=> "bbb"
irb(main):005:0>

配列の各要素には、数値でも文字列でもその他オブジェクトも格納できます。

irb(main):005:0> a = [1,"aaa",2,"bbb"]
=> [1, "aaa", 2, "bbb"]
irb(main):006:0> a[0]
=> 1
irb(main):007:0> a[1]
=> "aaa"
irb(main):008:0>

文字列の配列を作成するときに、クォートが面倒なら、%wが使えます。

irb(main):008:0> a = %w(aaa bbb ccc ddd eee)
=> ["aaa", "bbb", "ccc", "ddd", "eee"]
irb(main):009:0> a[3]
=> "ddd"
irb(main):010:0>

Perlと同じく空白を含む文字列を要素にできません。

要素のサイズを取得するには、sizeメソッドを使います。

irb(main):010:0> a.size
=> 5
irb(main):011:0>

配列から配列を取り出したいなら、スライスが使えます。
インデックスを指定して範囲取得するなら、.(ピリオド)を使い、変数名[インデックス..インデックス]、と指定します。(…でも可)

irb(main):011:0> a[1..3]
=> ["bbb", "ccc", "ddd"]
irb(main):012:0>

インデックスと、取得する要素数を指定する場合は、変数名[インデックス,要素数]と指定します。

irb(main):012:0> a[1,3]
=> ["bbb", "ccc", "ddd"]
irb(main):013:0> a[1,4]
=> ["bbb", "ccc", "ddd", "eee"]
irb(main):014:0>

Ruby 連想配列

Rubyの連想配列もPerlと同じくハッシュと呼ばれます。定義するには{}で囲んで、キーと値を書きます。

takk@deb9:~$ irb
irb(main):001:0> a = {'dog' => '犬',
irb(main):002:1* 'cat' => '猫',
irb(main):003:1* 'fox' => '狐'}
=> {"dog"=>"犬", "cat"=>"猫", "fox"=>"狐"}
irb(main):004:0> a['cat']
=> "猫"
irb(main):005:0>

数値もキーでできます。

irb(main):001:0> a = {10 => '犬',
irb(main):002:1* 20 => '猫',
irb(main):003:1* 30 => '狐'}
=> {10=>"犬", 20=>"猫", 30=>"狐"}
irb(main):004:0> a[20]
=> "猫"
irb(main):005:0>

文字列や数値だけではなく、Rubyのハッシュではシンボルが使えます。:から始める名称はシンボルとなります。

irb(main):001:0> a = {:dog => '犬',
irb(main):002:1* :cat => '猫',
irb(main):003:1* :fox => '狐'}
=> {:dog=>"犬", :cat=>"猫", :fox=>"狐"}
irb(main):004:0> a[:fox]
=> "狐"
irb(main):005:0>

Perlの連想配列の定義は,
%変数名=( キー => 値, …)

で、参照するのは、
$変数名{キー}

でしたが、Perlと比べてRubyの方が分かりやすい気がします。連想配列なんだから、配列と同じアクセス方法って覚えやすいですし。

Rubyのシンボルが使える点に関しては、Perlでは文字列のクォートが省略できますので、Perlの方が短く書けるのではないでしょうか。

takk@deb9:~$ perl -e '%a=(dog=>"犬",cat=>"猫"); print "$a{cat}\n"'
猫
takk@deb9:~$

Perlでは=>は,にできるので、偶数個の配列をハッシュにするなんてこともできますね。

takk@deb9:~$ perl -e '@array=1..6;print "@array\n"; %hash = @array; print "$hash{3}\n"'
1 2 3 4 5 6
4
takk@deb9:~$

Ruby 読み込み

Rubyのテキスト読み込みです。

例のごとく読み込むファイルを作成します。

takk@deb9:~$ seq 25 | pr -t5J | tee sample.txt
1       6       11      16      21
2       7       12      17      22
3       8       13      18      23
4       9       14      19      24
5       10      15      20      25
takk@deb9:~$

openとgetsを使って読み込みしてみます。getsメソッドで一行だけ読み込んで表示するだけのスクリプトです。

takk@deb9:~$ cat read.rb
f=open("sample.txt")
line = f.gets
print line
f.close()

実行するとsample.txtの先頭の一行だけ表示されます。

takk@deb9:~$ ruby read.rb
1       6       11      16      21
takk@deb9:~$ 

繰り返し読み込んで全部表示するには、whileを使います。どの言語も似たようなものですね。

takk@deb9:~$ cat read.rb
f=open("sample.txt")
while line = f.gets
        print line
end
f.close()

実行結果です。

takk@deb9:~$ ruby read.rb
1       6       11      16      21
2       7       12      17      22
3       8       13      18      23
4       9       14      19      24
5       10      15      20      25
takk@deb9:~$ 

File.readで全行を一括で読み込めます。

takk@deb9:~$ cat read.rb
lines=File.read("sample.txt")
print lines
takk@deb9:~$ ruby read.rb
1       6       11      16      21
2       7       12      17      22
3       8       13      18      23
4       9       14      19      24
5       10      15      20      25
takk@deb9:~$ 

標準入力は$stdinで読めます。

takk@deb9:~$ seq 10 | ruby -e 'while line=$stdin.gets;print line;end'
1
2
3
4
5
6
7
8
9
10
takk@deb9:~$

しかもgetsの場合は、$stdinから読み込むのがデフォルトなので省略できます。

takk@deb9:~$ seq 10 | ruby -e 'while line=gets;print line;end'
1
2
3
4
5
6
7
8
9
10
takk@deb9:~$

Ruby 書き込み

読み込みはこんな感じでした。

takk@deb9:~$ cat read.rb
f=open("in.txt")
print f.gets
f.close()
takk@deb9:~$ ruby read.rb
HELLO
takk@deb9:~$

書き込みは読み込みの反対なのだから、もしかしてputs使うだけでは? と思い、やってみるとエラーになります。

takk@deb9:~$ cat write.rb
f=open("out.txt")
f.puts("HELLO")
f.close()
takk@deb9:~$ ruby write.rb
write-ng.rb:2:in `write': not opened for writing (IOError)
        from write-ng.rb:2:in `puts'
        from write-ng.rb:2:in `<main>'
takk@deb9:~$

読み込みの時は省略していましたが、書き込みモードを指定する必要があります。第2引数に”w”を指定します。

takk@deb9:~$ cat write.rb
f=open("out.txt","w")
f.puts("AAA")
f.close()
takk@deb9:~$ 

実行してみます。

takk@deb9:~$ ruby write.rb
takk@deb9:~$ cat out.txt
AAA
takk@deb9:~$

out.txtが新規作成されて、内容が書き込まれているようです。

openはFile.openでもよいです。

takk@deb9:~$ cat write.rb
f=File.open("out.txt","w")
f.puts("BBB")
f.close()
takk@deb9:~$ ruby write.rb
takk@deb9:~$ cat out.txt
BBB
takk@deb9:~$

openを使わずに一発で全行書き込むにはFile.writeを使います。

takk@deb9:~$ cat write-all.rb
File.write("out.txt","HELLO\nHELLO\n")
takk@deb9:~$ ruby write-all.rb
takk@deb9:~$ cat out.txt
HELLO
HELLO
takk@deb9:~$

配列の内容を書き込む場合は、ちょっと一工夫いりそうです。

takk@deb9:~$ cat write-all.rb
arr = %w(aaa bbb ccc ddd eee)
arr.push("")
File.write("out.txt",arr.join("\n"))
takk@deb9:~$ ruby write-all.rb
takk@deb9:~$ cat out.txt
aaa
bbb
ccc
ddd
eee
takk@deb9:~$

コメント

タイトルとURLをコピーしました