我是Perl的新手,想知道在以下场景中运行外部命令(称之为prg
)的方法:
prg
,只获得它的stdout
。prg
,只获得它的stderr
。prg
,分别得到它的stdout
和stderr
。您可以使用背景来执行您的外部程序并捕获其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执行它们,因此您可以使用重定向。
$output = `cmd`;
$output = `cmd 2>&1`;
$output = `cmd 2>&1 1>/dev/null`;
$output = `cmd 3>&1 1>&2 2>&3 3>&-`;
system("program args 1>program.stdout 2>program.stderr");
请注意Eugene的答案(不能评论他的答案),就在上面,交换SDTOUT和STDERR的语法在Unix上是有效的(类似于Unixen的shell,比如ksh,或者bash,我猜)但不是在Windows CMD下(错误:3>& was unexpected at this time.
)。
Windows上的Windows CMD和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]
请注意,无法将两个stderr和stdout作为qx或反引号命令的返回字符串。如果您确定生成的命令返回的错误文本的长度为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]
中)。如果没有,唯一的解决方案是使用如上所述的临时文件。