在 Perl 中,执行反引号的默认 shell 是 sh。我想改用 bash 来获得更丰富的语法。到目前为止,我发现建议的解决方案是
`bash -c \"echo a b\"`
明显的缺点是转义双引号,这意味着我将很难在我的 bash args 中使用双引号。例如,如果我想在 bash 中运行需要双引号的命令
echo "a'b"
上面的方法会很别扭。
Perl 的 system() 调用有解决这个问题的方法:使用 ARRAY args,
system("bash", "-c", qq(echo "a'b"));
这使我原来的 bash 命令保持不变,而且几乎总是如此。
我也想在反引号中使用 ARRAY args。可能吗?
最佳答案
例如,可以向 qx
提交列表;它被插入到一个字符串中,然后传递给 execvp
或 shell(参见 qx 和 this post 的第二部分和注释)。如果您需要一个 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 命令,而不是通过一个咬钉子来正确地转义并传递它,比如 String::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
委托(delegate)给系统上的默认类型 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具有很少的实用功能
使用 Capture::Tiny用你喜欢的语法包装一个
system
调用IPC::Run可以做所有这一切,然后做得更多
为什么要使用外部命令,而 Perl 的(远远)更丰富?它是一种完整的、非常完整的编程语言,而不是具有某些编程功能的命令解释器。如果您需要 shell 的功能,为什么不通过 shell 只运行那些东西,而在 Perl 中做所有其他事情呢?
关于bash - 使用 bash 的 Perl 反引号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71033653/