我是 Perl 新手,想知道prg
在以下情况下运行外部命令(调用它)的方法:
- 运行
prg
,得到它的stdout
唯一。 - 运行
prg
,得到它的stderr
唯一。 - 分别运行
prg
,得到它的stdout
andstderr
。
您可以使用 backtics 来执行您的外部程序并捕获其stdout
和stderr
.
默认情况下,反引号丢弃stderr
并仅返回stdout
外部程序的。所以
$output = `cmd`;
将捕获stdout
程序 cmd 并丢弃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 不受影响):
$output = `cmd`;
一起捕获命令的 STDERR 和 STDOUT:
$output = `cmd 2>&1`;
要捕获命令的 STDERR 但丢弃其 STDOUT(此处排序很重要):
$output = `cmd 2>&1 1>/dev/null`;
交换命令的 STDOUT 和 STDERR 以捕获 STDERR 但将其 STDOUT 保留为旧的 STDERR:
$output = `cmd 3>&1 1>&2 2>&3 3>&-`;
要分别读取命令的 STDOUT 和 STDERR,最简单的方法是将它们分别重定向到文件,然后在程序完成时从这些文件中读取:
system("program args 1>program.stdout 2>program.stderr");
您可以使用IPC::Open3或IPC::Run。另外,请阅读如何从perlfaq8的外部命令中捕获 STDERR 。
请注意上面 Eugene 的答案(无法评论他的答案),交换 SDTOUT 和 STDERR 的语法在 Unix 上有效(我猜是 ksh 或 bash 等类似 Unixen 的 shell),但在 Windows CMD 下无效(错误:)3>& was unexpected at this time.
。
Windows CMD 和 Windows 上的 Perl 下的适当语法是:
perl -e "$r=qx{nslookup 255.255.255.255 2>&1 1>&3 3>&2};
注意命令:
nslookup 255.255.255.255
将在 STDOUT 上产生(类似的东西):
Server: mymodem.lan
Address: fd37:c01e:a880::1
在 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]};"
你得到:Server: mymodem.lan
Address: fd37:c01e:a880::1
on STDOUT qx result=[*** mymodem.lan can't find 255.255.255.255: Non-existent domain]
然后
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:
你得到:Server: mymodem.lan
Address: fd37:c01e:a880::1
QED [fr:CQFD]
请注意,对于 qx 或反引号命令,不可能同时获取 stderr 和 stdout 作为返回字符串。如果您确定生成的命令返回的 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]
如果没有,唯一的解决方案是使用上述临时文件。