【发布时间】:2011-10-20 18:05:49
【问题描述】:
在shell中,我可以做到
$ cat name_of_file_with_a_lot_of_text | grep "What I am looking for"
在 Rails 控制台中,我是否可以实现类似的操作,例如当我运行命令并且输出很大时,尤其是数据库查询。
我知道将其输出为 YAML,但这不是我想要的。
谢谢。
【问题讨论】:
标签: ruby-on-rails ruby console grep
在shell中,我可以做到
$ cat name_of_file_with_a_lot_of_text | grep "What I am looking for"
在 Rails 控制台中,我是否可以实现类似的操作,例如当我运行命令并且输出很大时,尤其是数据库查询。
我知道将其输出为 YAML,但这不是我想要的。
谢谢。
【问题讨论】:
标签: ruby-on-rails ruby console grep
是的,你可以。该方法称为gr ...等待它...ep。 Ruby 的grep 适用于String、Array 和许多其他内置对象。例如要获取一个数字的所有to_xxx 方法,只需:
1.methods.grep(/to_/)
【讨论】:
我也有同样的问题,并且对 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,这样我就可以保留块的输出并在最后返回它。赢了。
EDIT 2您现在可以在这个 gem 中获得所有这些功能(以及更多!)https://github.com/FutureAdvisor/console_util
【讨论】: