通过RegEx从Open3.popen3的stdout中提取值并存储它

我是Ruby的新手,似乎无法找到获取外部命令输出的方法。 我需要提取命令返回的值。 现在我有这样的事情:

stdin, stdout, stderr, wait_thr = Open3.popen3("#{path}/foobar", configfile) if /exit 0/ =~ wait_thr.value.to_s runlog.puts("Foobar exited normally.\n") puts "Test completed." someoutputvalue = stdout.read("TX.*\s+(\d+)\s+") puts "Output value: " + someoutputvalue end 

但我显然没有在stdout上使用正确的方法,因为Ruby告诉我它不能将String转换为Integer。

这样做的正确方法是什么? 我在文档中找不到stdout可用的方法。 使用stout.read我正在使用Ruby 1.9.3。

更新

为了清楚起见,我正在尝试读取程序的输出,应用正则表达式,并将提取的值存储到变量中供以后使用。

因此,例如,如果输出是“TX So so so:28”,我想只获得“28”(我validation上面的正则表达式匹配我需要匹配的东西,我只是想知道如何将所提取的值存储在一个变量)。

所需的所有信息都在Popen3文档中 ,但您必须仔细阅读并仔细查看示例。 您也可以从Process文档中收集有用的信息。

也许这会“更好地”:

 require 'open3' captured_stdout = '' captured_stderr = '' exit_status = Open3.popen3(ENV, 'date') {|stdin, stdout, stderr, wait_thr| pid = wait_thr.pid # pid of the started process. stdin.close captured_stdout = stdout.read captured_stderr = stderr.read wait_thr.value # Process::Status object returned. } puts "STDOUT: " + captured_stdout puts "STDERR: " + captured_stderr puts "EXIT STATUS: " + (exit_status.success? ? 'succeeded' : 'failed') 

运行输出:

 STDOUT: Wed Jun 12 07:07:12 MST 2013 STDERR: EXIT STATUS: succeeded 

注意事项:

  • 您经常需要close stdin流。 如果被调用的应用程序期望在STDIN上输入它将挂起,直到它看到流关闭,然后将继续其处理。
  • stdinstdoutstderr是IO句柄,因此您必须阅读IO类文档以找出可用的方法。
  • 您必须使用putsprintwrite输出到stdin ,并从stdoutstderr readgets
  • exit_status不是字符串,它是Process :: Status类的一个实例。 你可以搞乱尝试从它的to_s版本解析,但不要。 而是使用访问器来查看它返回的内容。
  • 我传入ENV哈希,因此子程序可以访问父看到的整个环境。 没有必要这样做; 相反,如果您不希望孩子访问所有内容,您可以为孩子创建一个简化的环境,或者您可以通过更改值来混淆其​​对环境的看法。
  • 问题中stdout.read("TX.*\s+(\d+)\s+")的代码stdout.read("TX.*\s+(\d+)\s+")是,嗯…废话。 我不知道你在哪里得到它,因为Ruby的IO类中没有记录IO #read或IO.read 。

如果您不需要写入被调用代码的STDIN, capture3容易使用capture3

 require 'open3' stdout, stderr, exit_status = Open3.capture3('date') puts "STDOUT: " + stdout puts "STDERR: " + stderr puts "EXIT STATUS: " + (exit_status.success? ? 'succeeded' : 'failed') 

哪个输出:

 STDOUT: Wed Jun 12 07:23:23 MST 2013 STDERR: EXIT STATUS: succeeded 

使用正则表达式从字符串中提取值非常简单,并且Regexp文档很好地介绍了这一点。 从最后一个代码示例开始:

 stdout[/^\w+ (\w+ \d+) .+ (\d+)$/] puts "Today is: " + [$1, $2].join(' ') 

哪个输出:

 Today is: Jun 12 2013 

那是使用String.[]方法,它非常灵活。

另一种方法是使用“命名捕获”:

 /^\w+ (?\w+ \d+) .+ (?\d+)$/ =~ stdout puts "Today is: #{ mon_day } #{ year }" 

它输出相同的东西。 命名捕获的缺点是它们对于我认为稍微方便一点的速度较慢。


 "TX So and so: 28"[/\d+$/] => "28"