如何在找到特定行后扫描文件。第一个结果不计算在内。 例如(在找到“从这里开始”的行后搜索3s):
Sample file
1
3
3
4
begin here
2
3
3
1
4
预期输出为两个3s
答案 0 :(得分:4)
Ruby的..
运算符是你的朋友:
DATA.each_line do |line|
line.chomp!
next unless (line =~ /^begin here$/) .. false
puts line if line == '3'
end
__END__
1
3
3
4
begin here
2
3
3
1
4
将其保存到文件并运行它,您将看到:
3
3
..
(以及更加模糊的...
)来自Perl,对于这种特殊用途非常有用。
..
是一个双状态运算符,与if
或unless
一起使用以查找第一个条件line =~ /^begin here$/
。当满足该条件时,操作员坚持,即返回true直到第二次测试匹配,(返回true)。一旦发生这种情况,触发器就会再次开始返回false。
在这段代码中,我愚弄它总是返回true,因为第二次测试总是false
。换句话说,代码然后读到数据的末尾。
..
(和...
)真的非常有用,查找整个文件中出现的数据块。如果第二个条件测试发现块结束,..
将重置,代码将跳过文件,直到它找到下一个块启动,触发并再次开始捕获。
也有可能大多数人都没有看过__END__
或DATA
。 __END__
是一种告诉Ruby的方法,除此之外没有其他代码可以执行。 DATA
是一个内部文件句柄,指向__END__
后面的行,可以类似于IO和File对象。它对于提供脚本必须具有的数据非常有用,但并不一定要放入单独的文件中。在这种情况下,我假装__END__
之后的行是一个单独的文件。易于peasy。
答案 1 :(得分:1)
我会这样写。
<强>代码强>
def put3s(fname)
e = IO.foreach(FName)
until e.next.strip == "begin here"; end
loop { puts "3" if e.next.strip == "3" }
end
请注意,没有块的IO#foreach会返回一个枚举器。 foreach
是最好的朋友。
在达到枚举数的最后一个元素后,e.next
会引发StopIteration
异常。 Kernel#loop通过突破循环来处理异常。
示例强>
我们首先创建一个文件:
text =<<_
1
3
3
4
begin here
2
3
3
1
4
_
FName = "t"
File.write(FName, text)
然后执行方法
put3s(FName)
# 3
# 3