Rubyでファイルの特定行を取り出す方法

このQ&Aのポイント
  • Rubyのプログラムで特定行の文字列を取り出したい場合、ファイルを開いてreadlinesメソッドを使うことで実現できます。
  • ただし、特定行を複数取り出す場合、ファイルを複数回開く必要があります。
  • 行番号が連続している場合は、一度ファイルを開いた後に複数回のreadlinesメソッド呼び出しで対応できます。
回答を見る
  • ベストアンサー

ファイルの特定行を取り出したい.

こちらのサイトを参考にさせていただきました. http://www.namaraii.com/rubytips/?%A5%D5%A5%A1%A5%A4%A5%EB%A5%A2%A5%AF%A5%BB%A5%B9 やりたいことはファイルにアクセスして2行目,3行目の文字列をとってくることです. ===foo=== hoge hige foobar File::open("foo") {|content|  puts content.readlines[1]  puts content.readlines[2] } このようなプログラムだと, hige nil となります.ですが,以下のように分割するとうまくいきます. File::open("foo") {|content|  puts content.readlines[1] } File::open("foo") {|content|  puts content.readlines[2] } hige foobar できればopenは一回だけで済ませたいのですが可能でしょうか? Ruby初心者なのでくだらない質問かもしれませんが,ご教授ねがいます.

  • Ruby
  • 回答数4
  • ありがとう数8

質問者が選んだベストアンサー

  • ベストアンサー
  • notnot
  • ベストアンサー率47% (4848/10261)
回答No.4

No3です。 >Rubyのみ初心者です. よかった。 >>確認2:readlinesというメソッドはどういう機能を持ったメソッドだと思っていますか? >ファイルの内容が一行ずつ入った配列だと思ってます ファイルを行の配列のようにアクセスできるメソッドと思っているのなら間違いです。 ファイルから全データを読み込んで、それを配列の形で返すメソッドです。したがって、呼び出したことで、該当ファイルのファイルポインタ(ファイル中で次に読み取る文字位置)は末尾のEOFの所に行ってしまいます。二回目の呼び出しで、EOFに達したファイルを再度読むことになるので空が返ります。具体的には配列なので [] が返ります。 他の方がお書きのように、呼び出し結果の配列オブジェクトを保持しておいて、以降はそれをつかうといいです。

garusu
質問者

お礼

おお! なるほど,どうりで2回目はnilになるわけですね ありがとうございました.

その他の回答 (3)

  • notnot
  • ベストアンサー率47% (4848/10261)
回答No.3

確認1:Rubyの初心者とお書きですが、他の言語でのこういうプログラミング経験があって、Rubyのみ初心者なのか、あるいは、プログラミングそのものの初心者なのかによって、説明のポイントが異なりますが、どちらでしょうか? 後者だとすると、かなり説明が大変です。 確認2:readlinesというメソッドはどういう機能を持ったメソッドだと思っていますか?

garusu
質問者

補足

>確認1:Rubyの初心者とお書きですが、他の言語でのこういうプログラミング経験があって、Rubyのみ初心者なのか、あるいは、プログラミングそのものの初心者なのかによって、説明のポイントが異なりますが、どちらでしょうか? Rubyのみ初心者です. >確認2:readlinesというメソッドはどういう機能を持ったメソッドだと思っていますか? ファイルの内容が一行ずつ入った配列だと思ってます.

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

content.readlines でファイルの内容が丸ごと入った配列になっているので、 普通の配列で二番目と三番目を取るにはどうすればいいかと考えてみてはどうでしょう? あ、そう考えちゃっているから File::open("foo") {|content|  puts content.readlines[1]  puts content.readlines[2] } としちゃったんですね。 File::open("foo") {|content|  v = content.readlines puts v[1] puts v[2] } と同じだろうと考えちゃったのかもしれませんが違います。 なぜ違うのかはここでは説明しませんが、考えて分からないようなら補足に書いてください。 二つ目のように一時変数を作りたくないというのであれば#1の方の回答の他にも こう言ったものが考えられます。 File.open('foo').each_with_index { |line, index| puts line if index == 1 || index == 2 } puts((File.open('foo').readlines)[1..2]) open("foo") {|file| puts file.readlines[1..2] } open("foo") {|file| puts file.readlines.values_at(1, 2) } お好みでどうぞ。

garusu
質問者

補足

遅くなって済みません, わざわざ例を書いてくださってありがとうございます. >なぜ違うのかはここでは説明しませんが、考えて分からないようなら補足に書いてください。 すみません,まったく違いがわからないです. 書いて下さった例でも,結局readlines[1]という風にアクセスしてるんじゃないの?と疑問に思ってしまいます.

  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.1

案1) open( 'foo' ) do |fh| a = fh.readlines; p a[1]; p a[2]; end 案2) open( 'foo' ) do |fh| lino = 0; while fh.gets lino += 1; p $_ if lino == 2 || lino == 3; break if lino >= 3; end end

関連するQ&A

  • ファイルの中の特定の行だけを削除したい

    あるファイルの特定の行だけを削除したいのですが、高速に行う方法はありませんか? とあるファイルがあり、これは数行~数万行にも及ぶ可能性のある大規模なファイルです。 このファイルの、特定の行を検索してその行だけ削除し、空いてしまった行は詰めたいのですが、どのようにすれば高速に行えますか? かなり遅い方法だと、 xxx = "hoge\n" arr = [] f = open("file") f.each{|line| if line != xxx then arr<<line end } f.close open("file", "w").puts arr.join() などが考えられるのですが、遅すぎて使えないはずです。 速度が求められる処理のため、困ってます。 もしご存じの方がいらっしゃいましたら、教えて頂けませんか?

    • ベストアンサー
    • Ruby
  • 文字列検索

    文字列検索 テキストファイルの検索を行いたいです. 下記のようなサンプルファイルでfooを検索し, 含まれるならマッチした個数,含まれないならnilを返す関数を作りたいです. mecabを用いて形態素解析を1行ずつしようかと思ったんですが, 大量のファイルを処理する予定なので,オーバヘッドが気になります. 関数でgrepがあるみたいですが,マッチした行しか返されません. 標準関数で1行ずつよみこんで,1行のなかでマッチした回数を返す関数はありますか? --sample.txt-- foo foo bar bar foo hoge,hoge,hoge,hoge hage-hage-hage-foo -- end --

    • ベストアンサー
    • Ruby
  • 【ruby】特異クラスを使って,File.statをカスタムしたい

    File.statに、nameというメソッドを追加したいです。 st=File.stat('hoge.txt') puts st.name #=> hoge.txt 上記のように使いたいのです。 そこで、以下の様に書いてみました。(行頭のスペースは全角です) class File  class << self   def stat(file)    st=File::Stat.new(file)    class << st     def name      @file     end    end    st   end end end st=File.stat('./hoge.txt') puts st.name #=> nil 上記実行結果はnilが出力され、期待した結果は得られませんでした。 上記の様に書いた理由を以下に記します。 クラスメソッドstatは、file.rbのclass Fileの中に定義されていて、 stat.rbのFile::Stat.new(file)を戻り値としていました。 stat.rbのclass File::Statのinitializeでは、 def initialize(file)  @file = file  (略) end となっていたので、上記の様に書いてみたのですが、何が悪いのでしょうか? ご指導のほど、宜しくお願いいたします。

    • ベストアンサー
    • Ruby
  • Ruby WEBrick cgiからgifが最後まで送れない。

    以下のようなHTTPサーバをWinXp上で動かしました。 #$ruby = "C:/ruby/bin/ruby.exe" require 'webrick' srv = WEBrick::HTTPServer.new({ :BindAddress => 'xxx.xxx.xxx.xxx', :CGIInterpreter => "c:/ruby/bin/ruby.exe", :Port => 80 }) srv.mount("/", WEBrick::HTTPServlet::FileHandler, "./", {:FancyIndexing=>true}) srv.start そして、以下のようなCGIをよびます。 #!/usr/bin/ruby STDOUT.binmode open("hoge.gif", "r") do |f| f.binmode body = f.read puts "content-type: image/gif" puts "content-length: #{body.size.to_s}" puts "" print body end すると、content-length分のHTTPボディーが送られてきません。 2種類のgifで試しましたが、193byte/724byte、289byte/451byteでした。 バージョンは、ruby 1.8.6、WEBrick 1.3.1です。 何が原因でしょうか?

  • 2行読み込んで一行戻り、また2行読み込む

    2行読み込んで一行戻り、また2行読み込む はじめまして、現在、「2行読み込み、一行戻り、また2行読み込む」処理のものを作成しています。 具体的には、 A B C D E と5行に渡り記述されたファイルを上記の旨で表示させる場合、 A B B C C D D E としたいのですが、 filename = ARGV[0] ABCDE = [] file = open(filename) while f = file.gets do  f.chomp!   g = file.gets   g.chomp!  p f  p g end file.close とすると出力は "A" "B" "C" "D" abcde.rb:9: private method `chomp!' called for nil:NilClass (NoMethodError) もちろん2行読み込んで、そのまま次の2行を読み込む記述のため上記のようになってしまいます。 まとめますと、 「一行戻るための記述がわからないので、それを実現するための記述を教えてほしい」 ということです。 rewindを使うと先頭まで戻ってしまうのでどうしたらいいのかさっぱりです。 わかりづらくて非常に申し訳ない、初歩的であろう質問ですがよろしくお願いします。 rubyは1.8.6を使っています。

    • ベストアンサー
    • Ruby
  • ShellExecute で file://... をオープン

    VC++, MFC を使ってプログラムを書いています。 ShellExecute で file://C:/TEMP/foobar.exe?foo=bar をオープンすると、ちゃんと foobar.exe が起動されますが、クエリーの部分(foo=bar)の情報を取る方法がわかりません。 GetCommandLine で帰る文字列は foobar.exe までしかない。 GetEnvironmentStrings で帰る環境変数にも含まれない。 ? 以降の部分の文字列を取得する方法は無いのでしょうか?

  • JavaScriptの変数にCGIの出力を入れたい。

    呼ばれると文字"a"を出力するhttp://xxx/ret_a.cgiがあるとします。 JavaScriptの中で変数hogeに、このhttp://xxx/ret_a.cgiの出力を格納するにはどうしたらよいですか? http://xxx/ret_a.cgiの内容は以下のようなかんじです。 ------------------- ここから ------------------- #!/usr/local/bin/ruby puts "Content-Type:text/html\n\n" puts "<html>\n" puts "<head><title>test1</title></head>\n" puts "<body>\n" puts "a" puts "</body></html>\n" ------------------- ここまで ------------------- puts "a"だけだと、500 Internal Server Errorになってしまうので、 上記のようにしました。

  • 改行を行わない書き込みメソッド

    Rubyを使用しています。 いま,f = File.open(・・・)として, そこにある変数a, b, c, ・・・を同じ行に入力してしようとしています。 そこで,ary = [a, b, c, ・・・]という配列を作成し, f.puts ary と書いててみたのですが上手に行きません。 というのも,putsでは自動的に改行されてしまって, a,b,c・・・がそれぞれ別の行に入力されてしまうためです。 改行を行わずに書き込みを行う方法を教えていただけないでしょうか? お願いします。

  • ダブルクォートで囲まれた文字列の取り出し

    Windows環境でRuby 1.8.7を使用しております。 ----sample1.txt----- hoge"foo\"bar\"foo"hage"bar\"baz\"bar"hoge ------------------ ファイルから1行ずつテキストを読み込んで処理を行います。上のsample.txtの様な行を読み込んだ場合にダブルクォートで囲まれた部分 foo\"bar\"foo bar\"baz\"bar を取り出すのにはどの様な正規表現を用いればよろしいでしょうか? エスケープされたダブルクォートを除ける上手い方法がわかりません。 また、ダブルクォートで囲まれた部分が複数行にまたがる場合はどの様に処理をすれば良いでしょうか? -----sample2.txt----- hoge"foo \"bar\" baz" hage ---------------------- -----sample3.txt----- hoge"foo \"ba r\"baz" hage ---------------------- 最初の例のように1行の場合は File.foreach(file) do | line | …… end で良いのですが、複数行の場合には同じように単純には行きません。 ダブルクォートの数を数えて、奇数の場合は偶数になるまで次行をくっつける様な処理を考えているのですが、もっと適切な方法はありますか? 宜しくお願いします。

  • 正規表現で置換

    その1 $str = "ほげほげほげ<a href="http://xxxx.xxxx.xxx/xxxx/">ほげほげほげ</a>ほげほげ<br /><br /><img src="http://yyy.hoge.jp/hage/hige/xxxx.jpg" width="320" height="240" />ほげほげ"; ↓ $str = "ほげほげほげ<a href="http://xxxx.xxxx.xxx/xxxx/">ほげほげほげ</a>ほげほげ<br /><br /><img src="./foo/faa/fii/xxx.jpg" width="320" height="240" />ほげほげ"; その2 $str = "<img src="http://yyy.hoge.jp/hage/hige/xxxx.jpg" width="320" height="240" />ほげほげほげ<a href="http://xxxx.xxxx.xxx/xxxx/">ほげほげほげ</a>ほげほげ<br /><br /><img src="http://yyy.hoge.jp/hage/hige/xxxx.jpg" width="320" height="240" />ほげほげ"; ↓ $str = "<img src="./foo/xxxx.jpg" width="320" height="240" />ほげほげほげ<a href="http://xxxx.xxxx.xxx/xxxx/">ほげほげほげ</a>ほげほげ<br /><br /><img src="./foo/faa/fii/xxx.jpg" width="320" height="240" />ほげほげ"; このような文字列があった時に、次のように従って置換したいです。 1.imgのタグの内部に、「http://yyy.hoge.jp/hage/hige/xxx.jpg」という文字列があった場合、「./foo/faa/fii/xxx.jpg」という文字列に置き換える。 2.それ以外のURLの場合は置換しない。 3.その1とその2では「xxx.jpg」となっていますが、jpg以外の拡張子の場合も存在する。 4.日本語とURLの位置や個数はバラバラです。 5.URLの中のxxxとyyyは不定の文字列で、hage、hoge、hige、foo、faa、fiiは固定です。 6.使用している言語はPHPです。正規表現を1度だけでできれば理想的ですが、今回は2回に渡った処理でも問題ありません。 以上です。正しく処理できる正規表現、あるいは下記の正規表現の誤りを教えて頂ければ幸いです。 お手数ですが、よろしくお願い致します。 下記の方法では、うまくできませんでした。 $pattern = "/http:\/\/.*?hoge.jp\//"; $replacement = "./"; $str= preg_replace($pattern, $replacement, $str); $pattern2 = '/\/?hage\/hoge/'; $str = preg_replace($pattern2, '/foo/faa/fii', $str);

    • ベストアンサー
    • PHP

専門家に質問してみよう