我必须在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
答案 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')