假设我有这个脚本:
# prog.p6
my $info = run "uname";
运行prog.p6
时,我得到:
$ perl6 prog.p6
Linux
是否有一种方法可以存储返回值的字符串化版本,并防止将其输出到终端?
已经有一个similar question,但没有提供具体答案。
答案 0 :(得分:8)
您需要通过设置$*OUT
启用标准输出管道,否则默认为:out
。所以:
my $proc = run("uname", :out);
my $stdout = $proc.out;
say $stdout.slurp;
$stdout.close;
可以缩写为:
my $proc = run("uname", :out);
say $proc.out.slurp(:close);
如果要在stderr上捕获输出而不是在stdout上捕获输出,可以执行以下操作:
my $proc = run("uname", :out, :err);
say "[stdout] " ~ $proc.out.slurp(:close);
say "[stderr] " ~ $proc.err.slurp(:close);
或者如果要将stdout和stderr捕获到一个管道中,则:
my $proc = run("uname", :merge);
say "[stdout and stderr] " ~ $proc.out.slurp(:close);
最后,如果您不想捕获输出并且不希望将其输出到终端:
my $proc = run("uname", :!out, :!err);
exit( $proc.exitcode );
答案 1 :(得分:4)
此答案涵盖的解决方案很简洁。
有时候,它的弊端大于其缺点:
不存储结果代码。如果需要,请改用ugexe解决方案。
不将输出存储到stderr。如果需要,请改用ugexe解决方案。
潜在漏洞。下面对此进行说明。请考虑使用ugexe的解决方案。
下面说明的功能文档以the quote adverb :exec
开始。
q
最安全的变体使用单个q
:
say qx[ echo 42 ] # 42
如果出现错误,则构造返回一个空字符串,并且任何错误消息都将出现在stderr上。
此最安全的变体类似于传递给shell的单带引号的字符串,例如'foo'
。单引号字符串不interpolate,因此code injection attack没有漏洞。
也就是说,您要向外壳传递单个字符串,而该外壳可能不是您期望的外壳,因此它可能无法按您期望的那样解析字符串。
qq
以下行产生与q
行相同的结果,但使用的是最不安全的变体:
say qqx[ echo 42 ]
此双q
变体类似于双引号字符串("foo"
)。这种形式的字符串引用 does 是插值的,这意味着如果您在传递给shell的字符串中包含变量,则它受code injection attack约束。
答案 2 :(得分:4)
默认情况下,run
仅将STDOUT
和STDERR
传递到父进程的STDOUT
和STDERR
。
您必须告诉它做其他事情。
最简单的方法是只给它:out
,告诉它保留STDOUT
。 (:out(True)
的缩写)
my $proc = run 'uname', :out;
my $result = $proc.out.slurp(:close);
my $proc = run 'uname', :out;
for $proc.out.lines(:close) {
.say;
}
您还可以有效地告诉它仅将STDOUT
发送到/dev/null
到:!out
。 (:out(False)
的缩写)
:out
可以做更多的事情
{
my $file will leave {.close} = open :w, 'test.out';
run 'uname', :out($file); # write directly to a file
}
print slurp 'test.out'; # Linux
my $proc = run 'uname', :out;
react {
whenever $proc.out.Supply {
.print
LAST {
$proc.out.close;
done; # in case there are other whenevers
}
}
}
如果您要执行最后一个操作,最好使用Proc :: Async。