仅在文件中的某个点之后搜索和匹配字符串

时间:2014-10-30 22:46:03

标签: ruby

如何在找到特定行后扫描文件。第一个结果不计算在内。 例如(在找到“从这里开始”的行后搜索3s):

Sample file
1
3
3
4
begin here
2
3
3
1
4

预期输出为两个3s

2 个答案:

答案 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,对于这种特殊用途非常有用。

..是一个双状态运算符,与ifunless一起使用以查找第一个条件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