在Perl中,执行backticks的默认shell是sh。我想切换到使用bash,因为它更丰富的语法。到目前为止,我发现建议的解决方案是
`bash -c \"echo a b\"`明显的缺点是转义双引号,这意味着我将有困难使用双引号在我的bash。例如,如果我想在bash中运行需要双引号的命令
echo "a'b"上面的方法会很尴尬。
Perl的system()调用有一个解决方案:要使用数组args,
system("bash", "-c", qq(echo "a'b"));这使我原来的bash命令保持不变,而且几乎总是如此。
我也想在后排使用数组args。有可能吗?
发布于 2022-02-08 19:12:19
捕捉:微小是一个非常好的选择:如概要所示,您可以这样做
use Capture::Tiny 'capture';
my ($output, $error_output, $exit_code) = capture {
system(@whatever);
};以及在capture_stdout内部使用系统,如果您想要更简单的回退行为。
另外,它是非常通用的,使用Perl代码(甚至是执行奇怪操作的Perl代码)以及外部程序,所以在工具箱中使用它是件好事。
发布于 2022-02-08 18:07:29
首先,可以向qx提交一个列表;它被内插到一个字符串中,然后传递给execvp或shell (参见qx,以及这个职位和注释的第二部分)。如果您需要一个shell,那么该字符串可能包含shell元字符,因此它通过shell进行。
my @cmd = qw(ls -l "dir with spaces");
#my @cmd = qw(ls -l "dir with spaces" > outfile);
my @out = qx(@cmd);
print for @out;我创建了一个"dir with spaces"目录,其中包含一个文件以进行测试。(对于带有引号的命令,可以使用shell。)
接下来,我原则上建议使用一个模块来编写这些shell命令,而不是通过咬钉子器来正确地转义和传递它,比如弦乐:ShellQuote。
use String::ShellQuote qw(shell_quote);
my @cmd = ('ls', '-l', q(dir with spaces));
my $quoted = shell_quote(@cmd);;
my @out = qx($quoted);
#my @out = qx($quoted > outfile);
print for @out;我使用单引号的q(...)运算符形式来演示另一种方法(对于包含单引号也很有用);对于这个简单的示例来说,这是不必要的。人们仍然需要谨慎对待细节;这是使用复杂的外部命令的本质,任何方法或工具都无法完全避免。
至于运行bash,请注意,通常情况下,sh委托给系统上的默认排序shell,而在许多系统上使用的是bash。但是,如果它不在您的命令中,那么在命令中使用bash -c的一种方法是首先准备命令,然后将其添加到qx字符串中
my @cmd = ('ls', '-l', q(dir with spaces));
my $quoted = shell_quote(@cmd);
my @out = qx(bash -c "$quoted");
#my @out = qx(bash -c "$quoted" > outfile);
print for @out;我还想给你几张纸条:
qx是一个古老的恶魔。使用现代工具/模块运行外部命令如何?为了准备所涉及的bash字符串,可能还有更多的工作要做,但是其他的事情都会更好。有很多选择。例如- [IPC::System::Simple](https://metacpan.org/pod/IPC::System::Simple) with its few utility functions- Use [Capture::Tiny](https://metacpan.org/pod/Capture::Tiny) to wrap a `system` call with syntax you prefer- The [IPC::Run](https://metacpan.org/pod/IPC::Run) can do any and all of this and then way way more发布于 2022-02-08 15:42:20
我有下面的潜艇可以工作
sub bash_output {
my ($cmd) = @_;
open my $ifh, "-|", "bash", "-c", $cmd or die "cannot open file handler: $!";
my $output = "";
while (<$ifh>) {
$output .= $_;
}
close $ifh;
return $output;
}
print "test bash_output()\n";
my @strings = (
qq(echo "a'b"),
'echo $BASH_VERSION',
'[[ "abcde" =~ bcd ]] && echo matched',
'i=1; ((i++)); echo $i',
);
for my $s (@strings) {
print "bash_output($s) = ", bash_output($s), "\n";
}输出是
bash_output(echo "a'b") = a'b
bash_output(echo $BASH_VERSION) = 4.4.20(1)-release
bash_output([[ "abcde" =~ bcd ]] && echo matched) = matched
bash_output(i=1; ((i++)); echo $i) = 2我的回答是冗长的,但它满足了我的需要。我本来希望Perl有一个内置的解决方案,就像它如何处理system()调用一样,我仍然希望。
https://stackoverflow.com/questions/71033653
复制相似问题