通过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上输入它将挂起,直到它看到流关闭,然后将继续其处理。 -
stdin
,stdout
,stderr
是IO句柄,因此您必须阅读IO类文档以找出可用的方法。 - 您必须使用
puts
,print
或write
输出到stdin
,并从stdout
和stderr
read
或gets
。 -
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"