如何迭代popen输出?

时间:2012-12-05 21:38:38

标签: ruby

我有这个简单的ruby脚本:

redcricket@dev-006:~$ cat simple.rb  
#!/usr/local/bin/ruby

IO.popen 'ls -l', 'r+' do |f|
        puts f.gets
end

当我运行它时,我得到的唯一输出就是这个......

redcricket@dev-006:~$ ./simple.rb  
total 32

......我的期望是......

redcricket@smp-mig-dev-006:~$ ls -l
total 32
drwxr-xr-x  4 redcricket co 4096 Dec  5 12:23 applications
-rw-r--r--  1 redcricket co  464 Oct  5 16:23 config
drwxr-xr-x 72 redcricket co 4096 Dec  5 15:11 docs
drwxr-xr-x  3 root    root  4096 Dec  5 12:14 oradiag_root
drwxr-xr-x  5 redcricket co 4096 Dec  5 16:22 platform
-rwxr-xr-x  1 redcricket co  373 Dec  5 16:30 process_yum_output.rb
-rwxr-xr-x  1 redcricket co 2159 Nov 28 16:24 SetupSSHPK.sh
-rwxr-xr-x  1 redcricket co  142 Dec  5 16:31 simple.rb

......我想我需要以某种方式迭代f.gets?

谢谢!

4 个答案:

答案 0 :(得分:4)

传递给IO#popen的块只执行一次。这不是一个循环。想象一下作为File¹传递给块的对象。如果IO#popen的第二个参数是"r",您可以阅读File;如果是"w"你可以写信给它。在控制流离开块之后,子进程应该已经死了,用于访问它的IO对象既不再有效也不再可用。

如果你想获得一个行数组,请在块的参数上调用readlines。如果要迭代它们,请调用each,即

IO.popen("ls", "r") { |io| io.each { |line| puts line } }

¹确切地说,它是IO的实例。

答案 1 :(得分:3)

Ruby IO#gets method只返回IO对象的下一行输入。

为了得到你可以反复调用的所有行,直到它为零,或者调用read来获取整个字符串,或者readlines来获取数组中的输入行

IO.popen('ls -l','r') { |f| puts $_ while f.gets }
IO.popen('ls -l','r') { |f| puts f.read }
IO.popen('ls -l','r') { |f| puts f.readlines }

答案 2 :(得分:2)

我喜欢:

IO.popen 'ls -l', 'r+' do |f|
  puts f.gets until f.eof?
end

答案 3 :(得分:2)

传递给IO.popen的块只被调用一次,传递一个IO对象来表示创建的管道。

由于您只在该对象上调用gets一次,因此您只会从该命令接收一行输出。要获得更多行,您需要迭代IO对象:

IO.popen %w{ls -l}, 'r' do |pipe|
  pipe.each do |line|
    puts "|#{line}"
  end
end