如何在 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)
在大多数情况下,您可以使用
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:
您可以使用 IPC::Open3 或 IPC::Run。另外,请阅读 如何我从 perlfaq8 的外部命令 捕获 STDERR。
You can use IPC::Open3 or IPC::Run. Also, read How can I capture STDERR from an external command from perlfaq8.
请注意上面 Eugene 的答案(无法评论他的答案),交换 SDTOUT 和 STDERR 的语法在 Unix 上有效(类似 Unixen 的 shell,如 ksh 或我猜的 bash),但在 Windows CMD 下无效(错误:
3>&此时是意外的。
)。Windows CMD 和 Windows 上的 Perl 下的适当语法是:
请注意,该命令:
: 上生成(类似的内容)
将在 STDOUT:和 STDERR
:您可以测试此语法是否与以下 CMD/Perl 语法一起使用:
首先:
您会得到:
服务器:mymodem.lan
地址:fd37:c01e:a880::1
在 STDOUT qx result=[*** mymodem.lan 找不到 255.255.255.255: 不存在的域]
然后
你得到:
服务器:mymodem.lan
地址:fd37:c01e:a880::1
QED [fr:CQFD]
请注意,不可能同时获取 stderr 和 stdout 作为 qx 或反引号命令的返回字符串。如果您确定生成的命令返回的 err 文本长度为 N 行,您仍然可以将 STDERR 重定向到 STDOUT,就像 Eugene 和其他人所描述的那样,但将 qx 返回的文本捕获在数组中,而不是作为标量字符串。 STDERR 流将在 STDOUT 之前返回到数组中,以便数组的前 N 行是 SDTERR 行。喜欢:
但当然,您必须确保 STDERR 上有 错误文本,并且严格包含 N 行(存储在
@r[0..N- 1]
)。如果没有,唯一的解决方案是使用如上所述的临时文件。Beware about the answer of Eugene (can't comment on his answer), just above, that the syntax to exchange SDTOUT and STDERR is valid on Unixes (Unixen-like shells such as ksh, or bash I guess) but not under Windows CMD (error:
3>& was unexpected at this time.
).The appropriate syntax under Windows CMD and Perl on Windows is:
Note that the command:
will produce (something like) on STDOUT:
and on STDERR:
You can test that this syntax works with the following CMD/Perl syntax:
First:
you get:
Server: mymodem.lan
Address: fd37:c01e:a880::1
on STDOUT qx result=[*** mymodem.lan can't find 255.255.255.255: Non-existent domain]
Then
you get:
Server: mymodem.lan
Address: fd37:c01e:a880::1
QED [fr:CQFD]
Note that it is not possible to get BOTH stderr and stdout as returned string for a qx or backticks command. If you know for sure that the err text returned by your spawned command is of length N lines, you can still redirect STDERR to STDOUT like describe by Eugene and others but capture your qx returned text in an array instead of as scalar string. The STDERR flow will be returned into the array before the STDOUT so that the N first lines of your array are the SDTERR lines. Like:
But of course you must be sure that there is an err text on STDERR and of strictly N lines (stored in
@r[0..N-1]
). If not, the only solution is using temp files as described above.您可以使用 backtics 来执行外部程序并捕获其
stdout
和stderr
。默认情况下,反引号会丢弃
stderr
并仅返回外部程序的stdout
。因此将捕获程序cmd的
stdout
并丢弃<代码>stderr。要仅捕获
stderr
,您可以使用 shell 的文件描述符:要捕获
stdout
和stderr
,您可以执行以下操作:使用上面的内容,您将无法区分
stderr
和stdout
。要将stdout
与stderr
分开,可以将两者重定向到单独的文件并读取文件:You can use the backtics to execute your external program and capture its
stdout
andstderr
.By default the backticks discard the
stderr
and return only thestdout
of the external program.SoWill capture the
stdout
of the program cmd and discardstderr
.To capture only
stderr
you can use the shell's file descriptors as:To capture both
stdout
andstderr
you can do:Using the above you'll not be able to differenciate
stderr
fromstdout
. To separtestdout
fromstderr
can redirect both to a separate file and read the files: