我注意到当我在 perl 中使用反引号时,命令是使用 sh 而不是 bash 执行的,这给了我一些问题。
我怎样才能改变这种行为,以便 perl 将使用 bash?
PS。我试图运行的命令是:
paste filename <(cut -d \" \" -f 2 filename2 | grep -v mean) >> filename3
尝试
`bash -c \"your command with args\"`
我相当确定 -c 的参数被解释为 bash 解释其命令行的方式。诀窍是保护它免受sh
- 这就是引号的用途。
“系统外壳”通常不是可变的。请参阅perldoc -f exec:
如果 LIST 中有多个参数,或者如果 LIST 是具有多个值的数组,则使用 LIST 中的参数调用 execvp(3)。如果只有一个标量参数或其中包含一个元素的数组,则检查参数是否有 shell 元字符,如果有,则将整个参数传递给系统的命令 shell 进行解析(这是“/bin/sh -c" 在 Unix 平台上,但在其他平台上有所不同)。
如果您确实需要 bash 来执行特定任务,请考虑显式调用它:
my $result = `/usr/bin/bash command arguments`;
甚至:
open my $bash_handle, '| /usr/bin/bash' or die "Cannot open bash: $!";
print $bash_handle 'command arguments';
您还可以将 bash 命令放入 .sh 文件并直接调用它:
my $result = `/usr/bin/bash script.pl`;
这个例子对我有用:
$ perl -e 'print `/bin/bash -c "echo <(pwd)"`'
/dev/fd/63
为了处理运行 bash 和嵌套引号,本文提供了最佳解决方案:如何在 Perl 的 system() 中使用 bash 语法?
my @args = ( "bash", "-c", "diff <(ls -l) <(ls -al)" );
system(@args);
我以为perl
会尊重该$SHELL
变量,但后来我想到它的行为实际上可能取决于您系统的exec
实现。在我看来,exec
将以文件的路径作为其第一个参数来执行 shell (/bin/sh)。
你总是可以qw/bash your-command/
的,不是吗?
创建一个 perl 子例程:
sub bash { return `cat << 'EOF' | /bin/bash\n$_[0]\nEOF\n`; }
并像下面这样使用它:
my $bash_cmd = 'paste filename <(cut -d " " -f 2 filename2 | grep -v mean) >> filename3';
print &bash($bash_cmd);
或者对多行命令使用 perl here-doc:
$bash_cmd = <<'EOF';
for (( i = 0; i < 10; i++ )); do
echo "${i}"
done
EOF
print &bash($bash_cmd);