默认情况下,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
Run Code Online (Sandbox Code Playgroud)
注意:不确定您是否需要 #sync 与 #sysread,但如果是这样,您可能也应该同步 STDOUT。另外,它一次将 8 个字节读入 mybuff - 您应该尝试这个值,它的效率非常低/CPU 负担很重。最后,这段代码很糟糕,需要重构,但它有效 - 使用ls -l ~/* | ruby rgrep.rb doc
(其中“doc”是搜索词)对其进行了测试
第二个注意事项:显然,我太忙于让它表现良好,但没能让它正确执行!正如 Dmitry Shevkoplyas 所指出的,如果在引发 EOFError 时 @overflow 中有文本,则该文本将丢失。我相信如果您将 catch 替换为以下内容,应该可以解决问题:
rescue EOFError => e
return false unless @overflow && @overflow.length > 0
output = @overflow
@overflow = ""
output
end
Run Code Online (Sandbox Code Playgroud)
(如果您觉得有帮助,请为德米特里的回答点赞!)
归档时间: |
|
查看次数: |
1291 次 |
最近记录: |