ruby - Ruby 中面向行的流式处理(如 grep)

标签 ruby pipe

默认情况下,Ruby 在缓冲模式下打开 $stdin$stdout。这意味着您不能使用 Ruby 执行类似 grep 的操作来过滤文本。有没有办法强制 Ruby 使用面向行的模式?我见过各种解决方案,包括 popen3(仅支持缓冲模式)和 pty(不单独处理 $stdout$stderr,这是我需要的)。

我该怎么做? Python 似乎也有同样的不足。

最佳答案

看起来你最好的选择是使用 STDOUT.syswrite 和 STDOUT.sysread - 下面的代码似乎有相当好的性能,尽管是丑陋的代码:

STDIN.sync = true
STDOUT.syswrite "Looking for #{ARGV[0]}\n"

def next_line
  mybuff = @overflow || ""
  until mybuff[/\n/]
    mybuff += STDIN.sysread(8)
  end
  overflow = mybuff.split("\n")
  out, *others = overflow
  @overflow = others.join("\n")
  out
rescue EOFError => e
  false  # NB: There's a bug here, see below
end

line = next_line
while line
  STDOUT.syswrite "#{line}\n" if line =~ /#{ARGV[0]}/i
  line = next_line
end

注意:不确定您是否需要#sync 和#sysread,但如果需要,您也应该同步STDOUT。此外,它一次将 8 个字节读入 mybuff - 你应该尝试这个值,它非常低效/CPU 繁重。最后,这段代码是 hacky,需要重构,但它可以工作——使用 ls -l ~/* | 测试它。 ruby rgrep.rb doc(其中“doc”是搜索词)


第二个注意事项:显然,我正忙着让它表现良好,但我没能让它正常表现!由于 Dmitry Shevkoplyas 有 noted ,如果在引发 EOFError 时@overflow 中有文本,则该文本将丢失。我相信如果您将 catch 替换为以下内容,它应该可以解决问题:

rescue EOFError => e
  return false unless @overflow && @overflow.length > 0
  output = @overflow
  @overflow = ""
  output
end

(如果您觉得有帮助,请为 Dmitry 的 answer 点赞!)

关于ruby - Ruby 中面向行的流式处理(如 grep),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6929112/

相关文章:

Ruby,捕获字符串的结尾部分

ruby - 以编程方式将电子邮件转换为 HTML 或 PDF

ruby-on-rails - 有没有类似 Ruby On Rails 的 Xampp?

c - 我了解 Unix 文件描述符在 C 中的工作原理吗?

python - 终止使用 python 子进程 Popen 启动的进程时如何关闭标准输出管道?

multithreading - 跨多线程管道客户端共享管道句柄

ruby - 重新请求错误: DirtyExit - Child process received unhandled signal

ruby-on-rails - f.select 不更新 false

python - 使用 python 中的代码模块重定向标准输入的输出?

java - 同步多个线程写入java中的同一个文件