2016-07-18 7 views
0

1つのファイルに入力しました。私の入力は、ファイル内の特定の一致する行だけを印刷します。

Index 
chapter 1 
    Introduction to ruby 
    ruby basics 
     Installing ruby 
     executing ruby 
chapter 2 
    Ruby class 
    Ruby object 
    Ruby method 
     Defining method 
     Calling method 
chapter 3 
    Ruby variable 
     Local variable 
     Class variable 
     Global variable 
     Instance variable 
chapter 4 
    . 
    . 
    . 

chapter 1chapter 234などのヘッダがあるです。私はセクションとして各章にn行を持つかもしれません。

特定の章の詳細をgrepする必要があります。私はすべてのセクションが必要です。私はchapter 1をgrepした場合、出力は、

chapter 1 
    Introduction to ruby 
    ruby basics 
     Installing ruby 
     executing ruby 

がどのように私は次の行に横断し、そしてそれをチェックしないのだろうか?私がそうするのを助けてください。

File.open 'test.txt' do |file| 
    chap_det=file.find { |line| line =~ /chapter 1:/ } 
    puts chap_det 
end 
+0

コードサンプルでファイルが読み取られません。何かをする方法を尋ねるときには、問題を解決するためのもう少し本格的な試みを見ることは良いことです。リンク先のページ「[mcve]」とhttp://meta.stackoverflow.com/q/261592/128421を含む「[ask]」をお読みください。 –

答えて

5

あなたが成功しinput文字列に内容を読んでいると仮定:

input = File.read('test.txt') 

chapter = ->(n) { /chapter\s+#{n}.*?(?=\R\w)/im } 
#⇒ #<Proc:[email protected](pry):59 (lambda)> 
input[chapter.(2)] 
#⇒ "chapter 2\n Ruby class\n (...skipped...) Calling method" 

正規表現はここchapter Nで始まり、キャリッジリターン/ラインフィード(任意の「改行」で終わる、すべてのものと一致し、 )に続いて「単語記号」が続きます。

puts input[chapter.(1)] 
# Chapter 1 
#  Introduction to ruby 
#  ruby basics 
#   Installing ruby 
#   executing ruby 

NB!それはに一致怠惰なドットを含まないので、コメントの中で、以下のWiktor第Stribiżewによって提案された正規表現は、少し速いです:

chapter = ->(n) { /chapter\s+#{n}\b.*(?:\R\B.*)*/i } 

証明:あなたが使用することもでき

input = %|Index 
Chapter 1 
    Introduction to ruby 
    ruby basics 
     Installing ruby 
     executing ruby 
chapter 2 
    Ruby class 
    Ruby object 
    Ruby method 
     Defining method 
     Calling method 
chapter 3 
    Ruby variable 
     Local variable 
     Class variable 
     Global variable 
     Instance variable 
Chapter 4 
    Introduction to ruby 
    ruby basics 
     Installing ruby 
     executing ruby 
chapter 5 
    Ruby class 
    Ruby object 
    Ruby method 
     Defining method 
     Calling method 
chapter 6 
    Ruby variable 
     Local variable 
     Class variable 
     Global variable 
     Instance variable 
| 

ch1 = ->(n) { /chapter\s+#{n}.*?(?=\R\w)/im } 
ch2 = ->(n) { /chapter\s+#{n}\b.*(?:\R\B.*)*/i } 

require 'benchmark' 

n = 500000 
Benchmark.bm(7) do |x| 
    x.report("1:") { n.times do input[ch1.(4)] end } 
    x.report("2:") { n.times do input[ch2.(4)] end } 
end 

#⇒     user  system  total  real 
# 1:  6.460000 0.000000 6.460000 ( 6.460074) 
# 2:  6.010000 0.000000 6.010000 ( 6.010000) 
+0

「\ R \ n」や「\ r」や「\ n」のいずれかにマッチするので、*改行で終わる*は改行で終わる*とする必要があります。 –

+0

@WiktorStribiżewええ、ありがとう、私はいつもこれを呼び出す方法について疑問に思っています:) – mudasobwa

+1

プラス..私はあなたの短い答えが本当に好きです。ありがとう。 –

0

次のコード:

chapter_lines = [] 
start = false 
chapter_number = 1 
File.open("test.txt", "r").each_line do |line| 
    start = true if line["chapter #{chapter_number}"] 
    start = false if line["chapter #{chapter_number+1}"] 
    chapter_lines << line.strip if start 
end  

puts chapter_lines.join("\n") 

編集:注記これは、章へのすべての参照が「章」ではなく「章」であると仮定しています。問題の中では、それは一度「章」であり、他の場所では「章」です。小額と資本の差c。

はそれが役に立てば幸い:)

ただ、好奇心のうち
+0

それは絶対に慣用的なルビーではありませんが、私はあなたがそれをテストした疑いがあります。 – mudasobwa

+0

あなたは正しいです。それはまったく慣用ではありません。あなたの答えを見てから少なくともそれは感じます。しかし、あなたの答えが出てくる前に、私は答えの起草を始めました。だから私はそれを保つべきだと思った。 –

+0

しかし、テストに関する限り。私はそれをテストしました!質問には私は、テキストファイル "第1章"と "第2章"を書く際にタイプミスがあると思います。 "第3章"他の場所... tiは小さな 'c'と仮定しました。 –

1

▶ N = 2 
▶ File.readlines('text.txt').select do |line| 
▷ true if line[/chapter #{N}/i]..line[/chapter #{N+1}/i] 
▷ end[0...-1].join $/ 
#⇒ "chapter 2\n (... skipped out ...) Calling method" 

それは正規表現ソリューションより≈3倍遅い:flip-flop operationを使用するソリューション。

0

これは一般的な問題であり、Rubyのslice_beforeまたはslice_afterメソッドが便利です。 slice_before使用:

doc = <<EOT 
Index 
chapter 1 
    Introduction to ruby 
    ruby basics 
     Installing ruby 
     executing ruby 
chapter 2 
    Ruby class 
    Ruby object 
    Ruby method 
     Defining method 
     Calling method 
chapter 3 
    Ruby variable 
     Local variable 
     Class variable 
     Global variable 
     Instance variable 
EOT 

chapters = doc.lines.slice_before(/^chapter/).to_a 
# => [["Index\n"], ["chapter 1\n", " Introduction to ruby\n", " ruby basics\n", "  Installing ruby\n", "  executing ruby\n"], ["chapter 2\n", " Ruby class\n", " Ruby object\n", " Ruby method\n", "  Defining method\n", "  Calling method\n"], ["chapter 3\n", " Ruby variable\n", "  Local variable\n", "  Class variable\n", "  Global variable\n", "  Instance variable\n"]] 

chapters.shift 

chapters[0] # => ["chapter 1\n", " Introduction to ruby\n", " ruby basics\n", "  Installing ruby\n", "  executing ruby\n"] 

chapters.shiftするためにインデックスを付け、各章の配列、その結果最初の要素を除去するために存在します。

そこから、必要であれば、それはjoinを使用して全体の「章」コンテンツを復元するのは簡単だが、行がすでに配列要素であるため、あなたはおそらく、彼らがそうであるようにそれらを保存しておきたいでしょう:

chapters[0].join # => "chapter 1\n Introduction to ruby\n ruby basics\n  Installing ruby\n  executing ruby\n" 

ファイルから読み込むので、ファイルがメモリに安全に収まる限り、File.readlines('file_to_read')を使用して読み込み、配列に変換してからslice_...で使用できます。

関連する問題