Ruby:逐行匹配范围

有没有办法在Ruby中执行以下Perl结构?

while( my $line = $file->each_line() ) { if($line =~ /first_line/ .. /end_line_I_care_about/) { do_something; # this will do something on a line per line basis on the range of the match } } 

在ruby中会读到如下内容:

 file.each_line do |line| if line.match(/first_line/) .. line.match(/end_line_I_care_about/) do_something; # this will only do it based on the first match not the range. end end 

将整个文件读入内存不是一种选择,我不知道该范围的大块有多大。

编辑:

谢谢你的答案,我得到的答案与我最初的代码基本相同。 我遇到的问题是“它可以测试正确的操作数,并在同样的评估中变为错误(如在awk中),但它仍然返回true一次。”

“如果您不希望它在下一次评估之前测试正确的操作数,就像在sed中一样,只需使用三个点(”……“)而不是两个。在所有其他方面,”……“的行为就像“……”。“

我正在标记正确的答案,指出我可以在同一个电话中关闭’..’。

作为参考,我使用的代码是:

 file.each_line do |line| if line.match(/first_line/) ... line.match(/end_line_I_care_about/) do_something; end end 

我不完全清楚Perl代码的确切语义,假设你想要完全一样。 Ruby确实具有类似的外观和工作方式,或者可能相同:作为条件的范围可用作切换。 您呈现的代码与我想象的完全一样。

但是有一些警告:

  1. 即使在达到最终条件后,也会一直读到行,直到到达文件末尾。 如果您希望结束条件接近大文件的开头,则这可能是性能考虑因素。

  2. 可以多次触发启动条件,重新打开“开关”,执行do_something并再次测试结束条件。 如果您的条件足够具体,或者如果您想要这种行为,这可能没问题,但这是需要注意的事情。

  3. 可以在调用启动条件的同时调用结束条件,仅为一行提供true。

这是另一种选择:

 started = false file.each_line do |line| started = true if line =~ /first_line_condition/ next unless started do_something() break if line =~ /last_line_condition/ end 

该代码读取文件的每一行,直到达到开始条件。 然后它会执行您喜欢的任何处理,直到您到达与您的结束条件匹配的行,直到它突破循环,从文件中读取不再有行。

是的,Ruby支持触发器:

 str = "aaa ON bbb OFF cccc ON ddd OFF eee" str.each_line do |line| puts line if line =~ /ON/..line =~ /OFF/ #puts line if line.match(/ON/)..line.match(/OFF/) #works too end 

输出:

 ON bbb OFF ON ddd OFF 

此解决方案最接近您的需求。 它几乎看起来像Perl,但这个有效的Ruby(虽然触发器操作员有点气馁)。 文件是逐行读取的,它没有完全加载到内存中。

 File.open("my_file.txt", "r").each_line do |line| if (line =~ /first_line/) .. (line =~ /end_line_I_care_about/) do_something end end 

括号是可选的,但它们提高了可读性。