【问题标题】:perl backticks: use bash instead of shperl 反引号:使用 bash 而不是 sh
【发布时间】:2011-03-23 09:23:46
【问题描述】:

我注意到当我在 perl 中使用反引号时,命令是使用 sh 而不是 bash 执行的,这给我带来了一些问题。

我怎样才能改变这种行为,以便 perl 使用 bash?

PS。我尝试运行的命令是:

paste filename <(cut -d \" \" -f 2 filename2 | grep -v mean) >> filename3

【问题讨论】:

  • 我很确定答案是“你不知道”。
  • 为什么?你的轻描淡写是什么?
  • sh 是通用的,bash 不是。
  • @ether:试试perl -wle'print `echo foo; ps --forest`' 看看sh
  • 你为什么还要掏腰包?你可以在纯粹的纯粹中做你想做的事。如果您想在 shell 中运行,请使用 shell 脚本。

标签: perl bash shell sh backticks


【解决方案1】:

为了处理运行bash和嵌套引号,这篇文章提供了最好的解决方案:How can I use bash syntax in Perl's system()?

my @args = ( "bash", "-c", "diff <(ls -l) <(ls -al)" );
system(@args);

【讨论】:

    【解决方案2】:

    创建一个 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);
    

    【讨论】:

      【解决方案3】:

      试试

      `bash -c \"your command with args\"`
      

      我相当肯定 -c 的参数被解释为 bash 解释其命令行的方式。诀窍是保护它免受sh 的侵害——这就是引号的用途。

      【讨论】:

      • 现在我遇到了像 -f 1 /tmp/file | 这样的错误。 grep -v mean) >> /tmp/file2: -c: line 0: 在寻找匹配的 `)' 时出现意外 EOF -f 1 /tmp/file3 | grep -v mean) >> /tmp/file4: -c: line 1: syntax error: unexpected end of file
      • 在我的示例中可能不需要 \。另外,不要在命令中使用 " - 使用 ' 。
      • 已解决!唯一对我有用的是:`bash -c 'my_command'`
      • 您也可以使用open my $fh, '-|', qw(bash -c), $cmdline 来避免引用问题,这几乎可以保证与`$cmdline` 完全一样——但界面不同。
      • 那些\ 没用,使用单引号比使用双引号更有意义。
      【解决方案4】:

      这个例子对我有用:

      $ perl -e 'print `/bin/bash -c "echo <(pwd)"`'
      /dev/fd/63
      

      【讨论】:

        【解决方案5】:

        我认为perl 会尊重$SHELL 变量,但后来我想到它的行为实际上可能取决于您系统的exec 实现。在我看来,exec

        将执行shell (/bin/sh) 的路径 文件作为它的第一个参数。

        qw/bash your-command/ 总是可以的,不是吗?

        【讨论】:

        • 我仍然收到“sh:语法错误:”(“意外”。有关我尝试运行的命令,请参阅原始帖子的评论。
        【解决方案6】:

        “系统外壳”通常不是可变的。见perldoc -f exec

        如果 LIST 中有多个参数,或者如果 LIST 是具有多个值的数组,则使用 LIST 中的参数调用 execvp(3)。如果 只有一个标量参数或包含一个元素的数组,检查参数是否有 shell 元字符,如果有,则 整个参数被传递给系统的命令外壳进行解析(在 Unix 平台上是“/bin/sh -c”,但在其他平台上有所不同)。

        如果您确实需要 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`;
        

        【讨论】:

        • 我仍然无法获得预期的行为。我想要 bash 的原因是我使用
        • @David:我不太明白你要运行什么命令;您可以使用代码格式将其编辑到您的问题中吗?
        猜你喜欢
        • 2012-06-07
        • 2015-05-15
        • 2021-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多