在shell中,我可以做到
$ cat name_of_file_with_a_lot_of_text | grep "What I am looking for"
在Rails控制台内部,我可以实现类似的功能,例如当我运行命令并且输出很大时,尤其是数据库查询。
我知道将它输出为YAML,但这不是我想要的。
感谢。
答案 0 :(得分:19)
是的,你可以。该方法称为gr ...等待它... ep。 Ruby的grep
适用于String
,Array
和许多其他内置对象。例如,要获取数字的所有to_xxx
方法,只需执行:
1.methods.grep(/to_/)
答案 1 :(得分:2)
我有同样的问题,并且对ream88的有点讽刺的反应不太满意,所以我决定对它进行一次破解。
# Allows you to filter output to the console using grep
# Ex:
# def foo
# puts "Some debugging output here"
# puts "The value of x is y"
# puts "The value of foo is bar"
# end
#
# grep_stdout(/value/) { foo }
# # => The value of x is y
# # => The value of foo is bar
# # => nil
def grep_stdout(expression)
# First we need to create a ruby "pipe" which is two sets of IO subclasses
# the first is read only (which represents a fake $stdin) and the second is
# write only (which represents a fake $stdout).
placeholder_in, placeholder_out = IO.pipe
# This child process handles the grep'ing. Its done in a child process so that
# it can operate in parallel with the main process.
pid = fork {
# sync $stdout so we can report any matches asap
$stdout.sync
# replace $stdout with placeholder_out
$stdin.reopen(placeholder_in)
# we have to close both placeholder_out and placeholder_in because all instances
# of an IO stream must be closed in order for it to ever reach EOF. There's two
# in this method; one in the child process and one in the main process.
placeholder_in.close
placeholder_out.close
# loop continuously until we reach EOF (which happens when all
# instances of placeholder_out have closed)
read_buffer = ''
loop do
begin
read_buffer << $stdin.readpartial(4096)
if line_match = read_buffer.match(/(.*\n)(.*)/)
print line_match[1].grep(expression) # grep complete lines
read_buffer = line_match[2] # save remaining partial line for the next iteration
end
rescue EOFError
print read_buffer.grep(expression) # grep any remaining partial line at EOF
break
end
end
}
# Save the original stdout out to a variable so we can use it again after this
# method is done
original_stdout = $stdout
# Redirect stdout to our pipe
$stdout = placeholder_out
# sync $stdout so that we can start operating on it as soon as possible
$stdout.sync
# allow the block to execute and save its return value
return_value = yield
# Set stdout back to the original so output will flow again
$stdout = original_stdout
# close the main instances of placeholder_in and placeholder_out
placeholder_in.close
placeholder_out.close
# Wait for the child processes to finish
Process.wait pid
# Because the connection to the database has a tendency to go away when calling this, reconnect here
# if we're using ActiveRecord
if defined?(ActiveRecord)
suppress_stdout { ActiveRecord::Base.verify_active_connections! }
end
# return the value of the block
return_value
end
我解决方案的明显缺点是输出丢失了。我不确定如何在不调用yield
两次的情况下解决这个问题。
编辑我已将我的答案更改为仅调用fork
一次,这样我就可以保留块的输出并在结尾处返回。取胜。
编辑2 您现在可以在此宝石中获得所有这些功能(以及更多!)https://github.com/FutureAdvisor/console_util