Ruby grep与行号

使用Ruby的Enumerable#grep方法获取匹配行与行号的最佳方法是什么。 (因为我们使用-n--line-number开关使用grep命令)。

至少在默认情况下,可枚举#grep不允许您这样做。 相反,我想出了:

 text = 'now is the time for all good men to come to the aid of their country' regex = /aid/ hits = text.lines.with_index(1).inject([]) { |m,i| m << i if (i[0][regex]); m } hits # => [["to come to the aid\n", 3]] 

也许是这样的:

 module Enumerable def lgrep(pattern) map.with_index.select{|e,| e =~ pattern} end end 

这不是优雅或高效,但为什么不在grepping之前对行进行编号?

你可以在Ruby 1.8.6中像这样使用它:

 require 'enumerator' class Array def grep_with_index(regex) self.enum_for(:each_with_index).select {|x,i| x =~ regex} end end arr = ['Foo', 'Bar', 'Gah'] arr.grep_with_index(/o/) # => [[0, 'Foo']] arr.grep_with_index(/a/) # => [[1, 'Bar'], [2, 'Gah']] 

或者,如果您正在寻找有关在Ruby中编写类似grep的实用程序的技巧。 像这样的东西应该工作:

 def greplines(filename, regex) lineno = 0 File.open(filename) do |file| file.each_line do |line| puts "#{lineno += 1}: #{line}" if line =~ regex end end end 
 >> lines=["one", "two", "tests"] => ["one", "two", "tests"] >> lines.grep(/test/){|x| puts "#{lines.index(x)+1}, #{x}" } 3, tests 

混搭Tin Man和ghostdog74的答案

 text = 'now is the time for all good men to come to the aid of their country' regex = /aid/ text.lines.grep(/aid/){|x| puts "#{text.lines.find_index(x)+1}, #{x}" } # => 3, to come to the aid 

锡人给出的解决方案的修改。 此代码段将返回一个散列,其中行号作为键,匹配行作为值。 这个也适用于ruby 1.8.7。

 text = 'now is the time for all good men to come to the aid of their country' regex = /aid/ hits = text.lines.each_with_index.inject({}) { |m, i| m.merge!({(i[1]+1) => i[0].chomp}) if (i[0][regex]); m} hits #=> {3=>"to come to the aid"} 

将文本放在文件中

test.log中

  now is the time for all good men to come to the aid of their country 

命令行(grep或awk命令的替代)

 ruby -ne ' puts $_ if $_=~/to the/' test.log 

试试这个吧

 ruby -na -e ' puts $F[2] if $_=~/the/' test.log 

同样

 ruby -na -e ' puts $_.split[2] if $_=~/the/' test.log 

这类似于awk命令。

另一个建议是:

lines.find_index{ |l| l=~ regex } lines.find_index{ |l| l=~ regex }