【问题标题】:Is there a way to achieve grep like functionality on output inside the Rails Console有没有办法在 Rails 控制台内的输出上实现类似 grep 的功能
【发布时间】: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


    【解决方案1】:

    是的,你可以。该方法称为gr ...等待它...ep。 Ruby 的grep 适用于StringArray 和许多其他内置对象。例如要获取一个数字的所有to_xxx 方法,只需:

     1.methods.grep(/to_/)
    

    【讨论】:

    • 我刚刚笑出声来......“gr.. 等等..ep”......就像一个很好的幽默;)
    【解决方案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,这样我就可以保留块的输出并在最后返回它。赢了。

    EDIT 2您现在可以在这个 gem 中获得所有这些功能(以及更多!)https://github.com/FutureAdvisor/console_util

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-14
      • 2011-05-19
      • 1970-01-01
      • 2012-05-13
      • 2014-11-08
      • 2016-05-05
      • 1970-01-01
      • 2015-02-12
      相关资源
      最近更新 更多