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

Ast*_*aar 5 ruby regex regex-group

我是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
Run Code Online (Sandbox Code Playgroud)

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

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

更新

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

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

the*_*Man 14

所需的所有信息都在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')
Run Code Online (Sandbox Code Playgroud)

运行输出:

STDOUT: Wed Jun 12 07:07:12 MST 2013
STDERR:
EXIT STATUS: succeeded
Run Code Online (Sandbox Code Playgroud)

注意事项:

  • You often have to close the stdin stream. If the called application expects input on STDIN it will hang until it sees the stream close, then will continue its processing.
  • stdin, stdout, stderr are IO handles, so you have to read the IO class documentation to find out what methods are available.
  • You have to output to stdin using puts, print or write, and read or gets from stdout and stderr.
  • exit_status isn't a string, it's an instance of the Process::Status class. You can mess with trying to parse from its to_s version, but don't. Instead use the accessors to see what it returned.
  • 我传入了ENV哈希,因此子程序可以访问父看到的整个环境.没有必要这样做; 相反,如果您不希望它可以访问所有内容,您可以为孩子创建一个简化的环境,或者您可以通过更改值来混淆其​​对环境的看法.
  • stdout.read("TX.*\s+(\d+)\s+")问题中贴出的代码是,嗯......胡说八道.我不知道你在哪里得到它,因为Ruby的IO类中没有记录IO#readIO.read.

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

require 'open3'

stdout, stderr, exit_status = Open3.capture3('date')

puts "STDOUT: " + stdout
puts "STDERR: " + stderr
puts "EXIT STATUS: " + (exit_status.success? ? 'succeeded' : 'failed')
Run Code Online (Sandbox Code Playgroud)

哪个输出:

STDOUT: Wed Jun 12 07:23:23 MST 2013
STDERR:
EXIT STATUS: succeeded
Run Code Online (Sandbox Code Playgroud)

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

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

哪个输出:

Today is: Jun 12 2013
Run Code Online (Sandbox Code Playgroud)

那是使用String.[]非常灵活的方法.

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

/^\w+ (?<mon_day>\w+ \d+) .+ (?<year>\d+)$/ =~ stdout
puts "Today is: #{ mon_day } #{ year }"
Run Code Online (Sandbox Code Playgroud)

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


"TX So and so: 28"[/\d+$/]
=> "28"
Run Code Online (Sandbox Code Playgroud)