如何在 Perl 中运行外部命令并捕获其输出?
我是 Perl 新手,想知道在以下情况下运行外部命令(称为 prg
)的方法:
- 运行
prg
,获取其仅标准输出。
- 运行
prg
,仅获取其stderr
。 - 运行
prg
,分别获取其stdout
和stderr
。
I'm new to Perl and want to know of a way to run an external command (call it prg
) in the following scenarios:
- Run
prg
, get itsstdout
only. - Run
prg
, get itsstderr
only. - Run
prg
, get itsstdout
andstderr
, separately.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
发布评论
评论(4)
请注意上面 Eugene 的答案(无法评论他的答案),交换 SDTOUT 和 STDERR 的语法在 Unix 上有效(类似 Unixen 的 shell,如 ksh 或我猜的 bash),但在 Windows CMD 下无效(错误:3>&此时是意外的。
)。
Windows CMD 和 Windows 上的 Perl 下的适当语法是:
perl -e "$r=qx{nslookup 255.255.255.255 2>&1 1>&3 3>&2};
请注意,该命令:
nslookup 255.255.255.255
: 上生成(类似的内容)
Server: mymodem.lan
Address: fd37:c01e:a880::1
将在 STDOUT:和 STDERR
*** mymodem.lan can't find 255.255.255.255: Non-existent domain
:您可以测试此语法是否与以下 CMD/Perl 语法一起使用:
首先:
perl -e "$r=qx{nslookup 255.255.255.255 2>&1 1>&3 3>&2}; $r=~s/[\n\r]//eg; print qq{on STDOUT qx result=[$r]};"
您会得到: 服务器:mymodem.lan
地址:fd37:c01e:a880::1
在 STDOUT qx result=[*** mymodem.lan 找不到 255.255.255.255: 不存在的域]
然后
perl -e "$r=qx{nslookup 255.255.255.255 2>&1 1>&3 3>&2}; $r=~s/[\n\r]//eg; print STDOUT qq{on STDOUT qx result=[$r]};" 2>&1 1>NUL:
你得到:服务器:mymodem.lan
地址:fd37:c01e:a880::1
QED [fr:CQFD]
请注意,不可能同时获取 stderr 和 stdout 作为 qx 或反引号命令的返回字符串。如果您确定生成的命令返回的 err 文本长度为 N 行,您仍然可以将 STDERR 重定向到 STDOUT,就像 Eugene 和其他人所描述的那样,但将 qx 返回的文本捕获在数组中,而不是作为标量字符串。 STDERR 流将在 STDOUT 之前返回到数组中,以便数组的前 N 行是 SDTERR 行。喜欢:
@r=qx{nslookup 255.255.255.255 2>&1};
$r[0] is "*** mymodem.lan can't find 255.255.255.255: Non-existent domain"
但当然,您必须确保 STDERR 上有 错误文本,并且严格包含 N 行(存储在 @r[0..N- 1]
)。如果没有,唯一的解决方案是使用如上所述的临时文件。
您可以使用 backtics 来执行外部程序并捕获其 stdout
和 stderr
。
默认情况下,反引号会丢弃stderr
并仅返回外部程序的stdout
。因此
$output = `cmd`;
将捕获程序cmd的stdout
并丢弃<代码>stderr。
要仅捕获 stderr
,您可以使用 shell 的文件描述符:
$output = `cmd 2>&1 1>/dev/null`;
要捕获 stdout
和 stderr
,您可以执行以下操作:
$output = `cmd 2>&1`;
使用上面的内容,您将无法区分 stderr
和 stdout
。要将 stdout
与 stderr
分开,可以将两者重定向到单独的文件并读取文件:
`cmd 1>stdout.txt 2>stderr.txt`;
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
在大多数情况下,您可以使用
qx//
运算符(或反引号)。它插入字符串并使用 shell 执行它们,因此您可以使用重定向。捕获命令的 STDOUT(STDERR 不受影响):
同时捕获命令的 STDERR 和 STDOUT:
要捕获命令的 STDERR 但丢弃其 STDOUT(此处顺序很重要):
交换命令的 STDOUT 和 STDERR 以捕获 STDERR,但保留其 STDOUT 以输出旧的 STDERR :
要分别读取命令的 STDOUT 及其 STDERR,最简单的方法是重定向它们分别保存到文件中,然后在程序完成时从这些文件中读取:
In most cases you can use the
qx//
operator (or backticks). It interpolates strings and executes them with the shell, so you can use redirections.To capture a command's STDOUT (STDERR is unaffected):
To capture a command's STDERR and STDOUT together:
To capture a command's STDERR but discard its STDOUT (ordering is important here):
To exchange a command's STDOUT and STDERR in order to capture the STDERR but leave its STDOUT to come out the old STDERR:
To read both a command's STDOUT and its STDERR separately, it's easiest to redirect them separately to files, and then read from those files when the program is done: