読者です 読者をやめる 読者になる 読者になる

第3章コマンドを作ろう

Ruby 勉強会

目次

  • コマンドラインからのデータの入力
  • ファイルからの読み込み
    • ファイルからテキストデータを読み込んで表示する
    • ファイルからテキストデータを1行ずつ読み込んで表示する
    • ファイルの中から特定のパターンの行のみを選んで出力する

コマンドラインで引数に取る

  • ARGV
    • ARGV[0]とか
  • キャスト
    • ARGV[1]to._i

ファイルからの読み込み

一気読み
filename = ARGV[0]
file = open(filename)
text = file.read
print text
file.close
一行づつ
  • 何かdoを不自然に感じてしまった
    • 1章を見ると省略可とも書いてあった
  • file.getsが条件…ではないのか
filename = ARGV[0]
file = open(filename)
while text = file.gets do
  print text
file.close

Regexpオブジェクト

  • まあ、説明いらねえか

おいらの問題

  • こんな感じのファイルを作って適当に名前付けて保存してください
吉田康久
21歳
つくば
  • ファイルから取り込んで配列に格納してください
  • その配列からハッシュを作って、以下のような出力を得るようなループを書いてください
名前:吉田康久
場所:つくば
年齢:21歳
  • 面倒なやりかたしてます。練習なので許してwww

おいらの回答1

filename = ARGV[0]
info = Array.new

file = open(filename)
while text = file.gets do
  info.push(text)
end
file.close

person = {}

person["名前"] = info[0]
person["年齢"] = info[1]
person["場所"] = info[2]

person.each {|key, value|
  print key,":",value
}

おいらの回答2

  • お題とは違うけど、似たようなことやるんだったらこっちのほうがいいか
  • 前の回答だと「person["名前"] = info[0]」の付近が最悪に感じるし
  • 書いたんだけど、arrayって配列なしで書きたい。が、どうすればよいが分からない
filename = ARGV[0]
file = open(filename)

array = Array.new
person = {}
while text = file.gets do
  array = text.chomp.split(',')
  person[array[0]] = array[1]
end

person.each {|key, value|
  print key,":",value,"\n"
}

おいらの問題2

コマンドライン引数から数字を受け取って、それらの数値の平均と分散を計算してください。

おいらの回答

require 'pp'

def sum(array)
  sum = 0
  array.each{ |i|
    sum += i.to_f
  }
  return sum.to_f
end

def mean(array)
  (sum(array)/array.size).to_f
end

def var(array)
  square = []
  (0..array.size-1).each{ |j|
    square[j] = array[j].to_f**2
  }
  var = mean(square) - mean(array)**2
  return (var*array.size/(array.size-1)).to_f
end

array = ARGV.map{|item| item.to_f}

puts sum(array)
puts mean(array)
puts var(array)

おいらの問題3.1

ファイルを読み込んで、横にファイル行数も付け加えて出力してください。一応ファイル名はコマンドラインから得ることにしておこう。

きょうはるびーべんきょうかいです。
もんだいみんなつくってきましたか?
きょうはるびーべんきょうかいです。
もんだいみんなつくってきましたか?
きょうはるびーべんきょうかいです。
もんだいみんなつくってきましたか?
きょうはるびーべんきょうかいです。
もんだいみんなつくってきましたか?
きょうはるびーべんきょうかいです。
もんだいみんなつくってきましたか?
きょうはるびーべんきょうかいです。
もんだいみんなつくってきましたか?
きょうはるびーべんきょうかいです。
もんだいみんなつくってきましたか?
きょうはるびーべんきょうかいです。
もんだいみんなつくってきましたか?
きょうはるびーべんきょうかいです。
もんだいみんなつくってきましたか?
きょうはるびーべんきょうかいです。
もんだいみんなつくってきましたか?
きょうはRubyべんきょうかいです。
もんだいみんなつくってきましたか?

っていうような文章がファイルにあったとして

 1:きょうはるびーべんきょうかいです。
 2:もんだいみんなつくってきましたか?
 3:きょうはるびーべんきょうかいです。
 4:もんだいみんなつくってきましたか?
 5:きょうはるびーべんきょうかいです。
 6:もんだいみんなつくってきましたか?
 7:きょうはるびーべんきょうかいです。
 8:もんだいみんなつくってきましたか?
 9:きょうはるびーべんきょうかいです。
10:もんだいみんなつくってきましたか?
11:きょうはるびーべんきょうかいです。
12:もんだいみんなつくってきましたか?
13:きょうはるびーべんきょうかいです。
14:もんだいみんなつくってきましたか?
15:きょうはるびーべんきょうかいです。
16:もんだいみんなつくってきましたか?
17:きょうはるびーべんきょうかいです。
18:もんだいみんなつくってきましたか?
19:きょうはるびーべんきょうかいです。
20:もんだいみんなつくってきましたか?
21:きょうはRuyべんきょうかいです。
22:もんだいみんなつくってきましたか?
23:

みたいな感じで出力。

  • 1から9までとかの数字は右寄せにする
  • 特定の言葉を含む行のみ、上の形式で表示
    • 特定の形式はコマンドラインから得る、とか

などに挑戦しているとよさげかも。

おいらの回答

filename = ARGV[0]
file = open(filename)

pattern = Regexp.new(ARGV[1])

count = 1
while text = file.gets do
  printf("%2s:%s",count,text) if pattern =~ text
  count += 1
end

file.close

おいらの問題3.2

  • さっきの問題にマッチした行±1行づつ表示するようにしてみましょう
require 'pp'

filename = ARGV[0]
file = open(filename)

pattern = Regexp.new(ARGV[1])

count = 1
text_array = []
while text = file.gets do
  text_array.push(text)
end
file.close

text_array.each_with_index{ |text,count|
  if pattern =~ text
    printf("%2s:%s",count-1,text_array[count-1]) 
    printf("%2s:%s",count,text_array[count]) 
    printf("%2s:%s",count+1,text_array[count+1]) 
  end
}