是否有自动方式在Ruby中进行shell管道?我正在尝试将以下shell代码转换为Ruby:
a | b | c... > ...
Run Code Online (Sandbox Code Playgroud)
但到目前为止我找到的唯一解决方案是自己做缓冲管理(简化,未经测试,希望它能得到我的意思):
a = IO.popen('a')
b = IO.popen('b', 'w+')
Thread.new(a, b) { |in, out|
out.write(in.readpartial(4096)) until in.eof?
out.close_write
}
# deal with b.read...
Run Code Online (Sandbox Code Playgroud)
我想我想要的是告诉popen使用现有流而不是创建新流的方法?或者,IO#merge方法将输出连接到b的输入?当滤波器数量增加时,我当前的方法变得相当笨拙.
我明白知道Kernel#system('a | b'),但我需要以通用的方式将Ruby过滤器与外部程序过滤器混合在一起.
小智 10
老问题,但由于它是谷歌的第一个结果之一,这里是答案:http://devver.wordpress.com/2009/10/12/ruby-subprocesses-part_3/(方法8)
简而言之 :
sh = Shell.new
sh.system("a") | sh.system("b") | sh.system("c")
Run Code Online (Sandbox Code Playgroud)
你可以做更复杂的事情
sh.echo(my_string) | sh.system("wc") > "file_path"
xml = (sh.echo(html) | sh.system("tidy", "-q")).to_s
Run Code Online (Sandbox Code Playgroud)
使用普通的 ruby,spawn具有可用于将进程与管道连接的重定向选项。
1)创建管道
r,w = IO.pipe
Run Code Online (Sandbox Code Playgroud)
2)用它来连接两个衍生进程
spawn(*%w[echo hello world], out: w)
spawn(*%w[tr a-z A-Z], in: r)
# => HELLO WORLD
Run Code Online (Sandbox Code Playgroud)
当然,您可以将其封装在类似sh.system上述 Shell 库中的内容中,并创建一个 |() 方法来进行互连。
标准库的 open3 模块有一些非常好的工具来处理这类事情,包括创建完整的管道。
如果a、b、 和c是通常从命令行访问的命令,那么您可以使用:
captured_output = `a | b | c`
Run Code Online (Sandbox Code Playgroud)
Ruby 将在子 shell 中运行命令并捕获 STDOUT。
如果您出于某种原因需要将输出路由到文件,那么您也可以将重定向添加到命令中。在这种情况下,STDOUT 不会返回给您,但您可以打开该文件并手动处理它:
`a | b | c > captured_output`
File.foreach('captured_output') do |li|
print li
end
Run Code Online (Sandbox Code Playgroud)
它没有提供与使用systemor一样多的控制popen3,但它很方便:
>> sin, sout, serr = Open3.popen3('ls -al | tail -1') #=> [#<IO:fd 4>, #<IO:fd 5>, #<IO:fd 7>, #<Thread:0x00000100bb8798 run>]
>> sout.read #=> "drwxr-xr-x 3 greg staff 102 Nov 2 21:01 python\n"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10210 次 |
| 最近记录: |