Bash的HereDoc中的Perl脚本

时间:2013-07-19 16:35:30

标签: perl bash

是否有可能稍微在bash脚本中编写perl脚本作为heredoc?

这不起作用(仅限示例)

#/bin/bash
perl <<EOF
while(<>) {
    chomp;
    print "xxx: $_\n";
}
EOF

这里有一些很好的方法如何将perl脚本嵌入到bash脚本中?想从bash脚本运行perl脚本,不要把它放到外部文件中。

4 个答案:

答案 0 :(得分:22)

这里的问题是脚本是在stdin上传递给perl的,所以尝试从脚本处理stdin不起作用。

1。字符串文字

perl -e '
while(<>) {
    chomp;
    print "xxx: $_\n";
}
'

使用字符串文字是最直接的写法,但如果Perl脚本本身包含单引号则不理想。

2。使用perl -e

#/bin/bash

script=$(cat <<'EOF'
while(<>) {
    chomp;
    print "xxx: $_\n";
}
EOF
)
perl -e "$script"

如果您使用perl -e将脚本传递给perl,那么您将不会遇到stdin问题,并且您可以在脚本中使用您喜欢的任何字符。不过,要做到这一点有点迂回。 Heredocs在stdin上产生输入,我们需要字符串。该怎么办?哦,我知道!这需要$(cat <<HEREDOC)

请务必使用<<'EOF'而非<<EOF来阻止bash在heredoc中进行变量插值。

你也可以在没有$script变量的情况下写这个,虽然它现在变得非常毛茸茸!

perl -e "$(cat <<'EOF'
while(<>) {
    chomp;
    print "xxx: $_\n";
}
EOF
)"

3。流程替换

perl <(cat <<'EOF'
while(<>) {
    chomp;
    print "xxx: $_\n";
}
EOF
)

沿着#2行,您可以使用称为进程替换的bash功能,它允许您编写<(cmd)来代替文件名。如果你使用它,你不需要-e,因为你现在传递perl文件名而不是字符串。

答案 1 :(得分:3)

你知道我从没想过这个。

答案是“是!”它确实有效。正如其他人所提到的,<STDIN>不能使用,但这很好用:

$ perl <<'EOF'
print "This is a test\n";
for $i ( (1..3) ) {
print "The count is $i\n";
}
print "End of my program\n";
EOF
This is a test
The count is 1
The count is 2
The count is 3
End of my program

在Kornshell和BASH中,如果用单引号括起你的文档字符串末尾,那么shell不会插入here文档。

答案 2 :(得分:2)

只有@John Kugelman的小修正回答。你可以消除无用的cat并使用:

read -r -d '' perlscript <<'EOF'
while(<>) {
    chomp;
    print "xxx: $_\n";
}
EOF

perl -e "$perlscript"

答案 3 :(得分:0)

以下是在bash中使用PERL HEREDOC脚本的另一种方法,并充分利用它。

    #!/bin/sh
    #If you are not passing bash var's and single quote the HEREDOC tag
    perl -le "$(cat <<'MYPL'
    # Best to build your out vars rather than writing directly
    # to the pipe until the end.
    my $STDERRdata="", $STDOUTdata="";
    while ($i=<STDIN>){ chomp $i;
        $STDOUTdata .= "To stdout\n";
        $STDERRdata .= "Write from within the heredoc\n";
    MYPL
    print $STDOUTdata; #Doing the pipe write at the end
    warn $STDERRdata;  #will save you a lot of frustration.
    )" [optional args] <myInputFile 1>prints.txt 2>warns.txt

    #!/bin/sh
    set WRITEWHAT="bash vars"
    #If you want to include your bash var's
    #Escape the $'s that are not bash vars, and double quote the HEREDOC tag
    perl -le "$(cat <<"MYPL"
    my $STDERRdata="", $STDOUTdata="";
    while (\$i=<STDIN>){ chomp \$i;
        \$STDOUTdata .= "To stdout\n";
        \$STDERRdata .= "Write $WRITEWHAT from within the heredoc\n";
    MYPL
    print \$STDOUTdata; #Doing the pipe write at the end
    warn \$STDERRdata;  #will save you a lot of frustration.
    )" [optional args] <myInputFile 1>prints.txt 2>warns.txt