用于从 Open3.popen3 标准输出中提取值的正则表达式 [英] RegEx for extracting a value from Open3.popen3 stdout

查看:52
本文介绍了用于从 Open3.popen3 标准输出中提取值的正则表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何获取外部命令的输出并从中提取值?

How do I get the output of an external command and extract values from it?

我有这样的事情:

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.

I'm not using the right method on stdout since Ruby tells me it can't convert String into Integer.

例如,如果输出是

"TX So and so:     28"

我只想得到28".我验证了上面的正则表达式匹配我需要匹配的内容,我只是想知道如何将提取的值存储在变量中.

I would like to get only "28". I validated that the regex above matches what I need to match, I'm only wondering how to store that extracted value in a variable.

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

What is the right way of doing this? I can't find anywhere in the documentation the methods available for stdout. I'm using stout.read from Ruby 1.9.3.

推荐答案

所有需要的信息都在 Popen3 文档,但您必须仔细阅读所有内容并仔细查看示例.您还可以从 流程文档 中收集有用的信息.

All the information needed is in the Popen3 documentation, but you have to read it all and look at the examples pretty carefully. You can also glean useful information from the Process docs too.

也许这会更好地解释它:

Maybe this will 'splain it better:

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

注意事项:

  • 您经常需要关闭stdin 流.如果被调用的应用程序需要 STDIN 上的输入,它将挂起直到看到流关闭,然后将继续处理.
  • stdinstdoutstderr 是IO 句柄,所以要阅读IO 类文档 以了解可用的方法.
  • 您必须使用putsprintwriteread<输出到stdin/code> 或 getsstdoutstderr.
  • exit_status 不是字符串,而是 Process::Status 类的实例.您可以尝试从其 to_s 版本进行解析,但不要这样做.而是使用访问器来查看它返回的内容.
  • 我传入了 ENV 哈希,因此子程序可以访问父程序看到的整个环境.没有必要这样做;相反,如果您不想让孩子访问所有内容,您可以为孩子创建一个简化的环境,或者您可以通过更改值来扰乱其对环境的看法.
  • 问题中发布的代码 stdout.read("TX.*\s+(\d+)\s+") 是,嗯......废话.我不知道你从哪里得到的,因为在 Ruby 的 IO 类中没有记录 IO#readIO.读取.
  • 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.
  • I passed in the ENV hash, so the child program had access to the entire environment the parent saw. It's not necessary to do that; Instead you can create a reduced environment for the child if you don't want it to have access to everything, or you can mess with its view of the environment by changing values.
  • The code stdout.read("TX.*\s+(\d+)\s+") posted in the question is, um... nonsense. I have no idea where you got that as nothing like that is documented in Ruby's IO class for IO#read or IO.read.

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

It's easier to use capture3 if you don't need to write to STDIN of the called code:

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


使用正则表达式从字符串中提取值是微不足道的,正则表达式文档.从最后一个代码示例开始:


Extracting a value from a string using a regular expression is trivial, and well covered by the Regexp documentation. Starting from the last code example:

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

输出:

Today is: Jun 12 2013

这是使用 字符串.[] 非常灵活的方法.

That's using the String.[] method which is extremely flexible.

另一种使用命名捕获":

An alternate is using "named captures":

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

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

which outputs the same thing. The downside to named captures is they're slower for what I consider a minor bit of convenience.

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

这篇关于用于从 Open3.popen3 标准输出中提取值的正则表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆