0

我必须在 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
4

3 回答 3

0

您可以使用 来做到这一点String#gsub,但您需要将一个选项传递给正则表达式,这将使点匹配换行符。

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
于 2012-08-07T14:54:27.127 回答
0

我喜欢避免使用正则表达式,除非它们确实是必要的。在这种情况下,它们不是。只需逐行遍历字符串,打印每一行。检测何时看到“# pattern 2”,然后停止打印线。检测何时看到“# end 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
于 2012-08-07T15:19:18.597 回答
0

喜欢Here文档的技巧,但是如果你想直接处理文件,这里有另一种解决方案,它使用pos和rewind(对不起,文件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')
于 2012-08-07T16:43:10.807 回答