删除ruby中的模式后的行

时间:2012-08-07 14:21:58

标签: ruby pattern-matching

我必须在Ruby中的文件模式之后删除一些行。例如,我有一个这样的文件:

# pattern 1
a
b
# end pattern 1
# pattern 2
a
b
c
d
# end pattern 2
# pattern 3
a
b
c
# end pattern 3

我想删除# pattern 2# end pattern 2之间的行 我想要的文件是:

# pattern 1
a
b
# end pattern 1
# pattern 3
a
b
c
# end pattern 3

3 个答案:

答案 0 :(得分:0)

您可以使用String#gsub执行此操作,但是您需要将选项传递给regex,这会使点匹配换行。

str = <<-STR
# pattern 1
a
b
# end pattern 1
# pattern 2
a
b
c
d
# end pattern 2
# pattern 3
a
b
c
# end pattern 3
STR

puts str.gsub(/(# pattern 2.*# end pattern 2\n)/m, '')
# >> # pattern 1
# >> a
# >> b
# >> # end pattern 1
# >> # pattern 3
# >> a
# >> b
# >> c
# >> # end pattern 3

答案 1 :(得分:0)

我喜欢避免使用正则表达式,除非它们确实是必要的。在这种情况下,他们不是。只需遍历字符串逐行打印每一行。当您看到“#pattern 2”然后停止打印行时检测。当您看到“#ndode pattern 2”并再次开始打印行时检测。这可以通过本地布尔变量轻松完成,你应该自己做一个练习,因为听起来你对Ruby知之甚少,不知道该尝试什么。

但是 Ruby中有一个很酷的技巧,它使变量变得不必要:

str = <<END
X
# pattern 2
Y
Z
# end pattern 2
Q
END

str.split("\n").each do |line|
  puts line unless (line=="# pattern 2")..(line=="# end pattern 2")
end

答案 2 :(得分:0)

喜欢Here文档的技巧,但如果你想直接处理文件,这里是另一个解决方案,它使用pos和倒带播放(对不起,没有文件io的异常处理):

def gsub_paragraph(options)
  regex_start = /^.*#{options[:pattern_start]}.*$/
  regex_stop = /^.*#{options[:pattern_stop]}.*$/

  f_read = File.new(options[:file_in], 'r')
  true until (line_pattern = regex_start.match(f_read.gets))
  pos_start = f_read.pos - line_pattern[0].length - 1
  f_read.rewind
  part_start = f_read.read(pos_start)

  true until (line_pattern = regex_stop.match(f_read.gets))
  pos_stop = f_read.pos
  part_stop = f_read.read(pos_stop)
  f_read.close

  f_write = File.new((options[:file_out] || options[:file_in]), 'w+')
  replacement = options[:replacement] || ''
  f_write.puts part_start + replacement + part_stop
  f_write.close
end


file = "gsub_in.txt"

# Output to a designated file other than source file, replace matched part
gsub_paragraph(:file_in => file, :pattern_start => 'pattern 2', :pattern_stop => 'end pattern 2', :replacement => "~~~I replaced sth here~~~\n", :file_out => 'gsub_out.txt')

# Output to a designated file other than source file, without replacement
gsub_paragraph(:file_in => file, :pattern_start => 'pattern 2', :pattern_stop => 'end pattern 2', :file_out => 'gsub_out.txt')

# Output to source file directly, without replacement
gsub_paragraph(:file_in => file, :pattern_start => 'pattern 2', :pattern_stop => 'end pattern 2')