Hatena::Grouprubyist

krystal: プログラミング超初心者(文系)

2009-01-08 (Thu)たのしいRuby練習問題

P - 306 練習問題(3)

21:43

  • Unixのduコマンドのように、再帰的に掘り下げて調べ表示するメソッドduを定義してみよう。
def du(path)
  size = FileTest.size(path)
  if FileTest.directory?(path)
    Dir.open(path){|dir|
      dir.each{|name|
        next if name == "."
        next if name == ".."
        size += du(File.join(path, name))
      }
    }
  end
  printf("%8d %s\n", size, path)
  return size  #size(数字)を返さないと、↑のduはprintfを返すことになるからnil。だから、size+nilは怒られる
end

2009-01-07 (Wed)たのしいRuby練習問題

P306 - FileクラスとDirクラスの練習問題

20:22

(1)

  • $:を使ってRubyが利用できるライブラリのファイル名を順に出力するメソッドprint_libraryメソッドを定義しよう
def print_library
  $:.each{|i|
    next if i == "."  #practiceという練習フォルダにいるから、"."をスキップしないと練習ファイル全部出てくる
    dir = Dir.open(i)
    dir.each{|name|
      if name =~ /\.rb$/
        puts name
      end
    }
    dir.close
  }
end
print_library

(2)

  • あるディレクトリに置かれているファイルとサブディレクトリを、そのサブディレクトリに入っているファイルやディレクトリごとコピーするメソッドdircopyを定義しよう。
  • このメソッドは2つの引数を取ります。 ----> dircopy(コピー元のディレクトリ名, コピー先のディレクトリ名)

つまずいてる。考え方はそんなに間違ってない気がするけど、うまく実装できてない。

ちゃんと動くようになったらまたアップする。

答えなどを参考にした。


require "ftools"

def dircopy(dir1, dir2)
  if FileTest.exist?(dir2)
    raise "Error : #{dir2} exists already."
  end
  
  Dir.open(dir1){|dir|
    Dir.mkdir(dir2)
    dir.each{|name|
      next if name == "."       
      next if name == ".."      
      path1 = File.join(dir1, name)
      path2 = File.join(dir2, name)
      st = File.lstat(path1)       #lstatを使うことでシンボリックリンクもコピーできるようになるらしい
      if st.file?
        File.copy(path1, path2)
      elsif st.directory?
        dircopy(path1, path2)
      elsif st.symlink?
        File.symlink(File.readlink(path1), path2)
      else
        $stderr.pus "unknown file type : #{path1}"
      end
    }
  }
end

dircopy("/rubima011-cgi", "/ruby/practice/temp")

「たのしいRuby」はちゃんと校正されたか疑問。かなりtypoがあったから。

2008-12-25 (Thu)たのしいRuby練習問題

★☆★☆★☆★☆★ ⊱❤❤❤Merry Christmas!!❤❤❤⊰ ★☆★☆★☆★☆★

19:41

P285 IOクラス練習問題(1)

  • あるファイルの内容を別のファイルにそのままコピーするメソッドcopy_fileを定義しよう
def copy_file(file1, file2)
  open(file1){|from|
    open(file2, "w"){|to|
      while line = from.gets
        to.write(line)
      end
    }
  }
end
copy_file("test.rb", "copy.rb")

コピー元であるfile1から一行ずつgetsして、コピー先ファイルであるfile2へwrite

[2009/01/06]先ほど本を読んだらこのような書き方があった

def copy_file(file1, file2)
  open(file1){|from|
    open(file2, "w"){|to|
      to.write(from.read)
    }
  }
end
copy_file("test.rb", "copy.rb")

P285 IOクラス練習問題(2)

  • Unixで使われるtailコマンドと似たことができるメソッドtailを定義しよう
def tail(line_num, file)
  arr = []
  arr2 = []
  open(file){|f|
    while line = f.gets
      arr << line
    end
  }
  for i in 1..line_num
    arr2 << arr.pop
  end
  puts arr2.reverse

end
tail(11, "copy.rb")

fileから内容を一行ずつ配列arrに入れて、配列arrからline_num回popしたもの(行)を別の配列arr2に入れる。arr2をreverseして出力。

readlinesを使ってみた
def tail(line_num, file)
  open(file) {|f|
    puts f.readlines[(f.readlines.size - line_num)..(f.readlines.size - 1)]
  }
end
tail(7, "copy.rb")

entottoentotto2008/12/25 20:09tail コマンドの魅力は -f オプションだと思います。

「tail.rb -f -n 10 some.log を実行したら、some.logの最後10行を出力したまま、終了せずに、some.logに何か追記されたらさらにそれを出力する。」ような tail.rb がほしいなぁ。> サンタさん

ちなみにファイルへの追記は >> を使うとできます。
$ echo "abc" >> some.log

krystalkrystal2009/01/06 13:18>entottoさん
コメントありがとうございます。
昨日vm wareを使ってtail -fコマンドを確認してみて、どういう動作するかが分かりました。やり方考えてみます。

2008-12-17 (Wed)たのしいRuby練習問題

P266 正規表現クラス

19:08

練習問題(1)

  • メルアドは「ローカルパート@ドメイン名」という形になってるから、ローカルパートを$1として、ドメイン名を$2として取得する正規表現を作る
str = "s.t.a.t.e_of_s.h.o.c.k123@hotmail.co.jp"
/(\w.*)@(\w.*)/ =~ str
local_part = $1
domain_name = $2
p local_part    #=>  "s.t.a.t.e_of_s.h.o.c.k123"
p domain_name   #=>  "hotmail.co.jp"

練習問題(2)

  • 「オブジェクト指向は難しい!なんて難しいんだ!」という文字列をgsubメソッドを使って「オブジェクト指向は簡単だ!なんて簡単なんだ!」という文字列に直す
str = "オブジェクト指向は難しい!なんて難しいんだ!"
p str.gsub(/難しい/, "簡単だ").gsub(/だん/, "なん")   #=>  "オブジェクト指向は簡単だ!なんて簡単なんだ!"

練習問題(3)

  • アルファベットとハイフンからなる文字列を与えれると、ハイフンで区切られた部分をCapitalizeするようなメソッドword_capitalizeを定義する
  • こんな感じで
p word_capitalize("in-reply-to")  #=> "In-Reply-To"
p word_capitalize("X-MAILER")  #=> "X-Mailer"
  • 私のコード
def word_capitalize(str)
  if /\w-*/ =~ str
    ary = Array.new
    str.split("-").each{|x|
      ary << x.capitalize
    }
    ary.join("-")
  end
end
p word_capitalize("out-of-the-box-to-the-sky")  #=> "Out-Of-The-Box-To-The-Sky"
p word_capitalize("GO-THE-DISTANCE")                 #=> "Go-The-Distance"

解答を見たらこれ練習になってないかもと思った。

  • CD-ROMによる(3)の解答はこの2つ:
def word_capitalize(str)
  return str.split(/\-/).collect{|w| w.capitalize}.join('-')
end

p word_capitalize("in-reply-to") #=> "In-Reply-To"
p word_capitalize("X-MAILER")    #=> "X-Mailer"
def word_capitalize(str)
  ret = ""
  str.scan(/(\w+)(\W*)/){|word, no_word|
    ret << word.capitalize + no_word
  }
  return ret
end

p word_capitalize("in-reply-to") #=> "In-Reply-To"
p word_capitalize("X-MAILER")    #=> "X-Mailer"