能否在bash脚本中使用heredoc的方式编写Perl脚本呢?
以下示例并不有效:
#/bin/bash
perl <<EOF
while(<>) {
chomp;
print "xxx: $_\n";
}
EOF
有没有一种好的方法将Perl脚本嵌入Bash脚本中?想要从Bash脚本中运行Perl脚本,但不想将其放入外部文件中。
问题在于脚本被传递到perl的标准输入上,因此尝试从脚本处理标准输入是行不通的。
perl -e '
while(<>) {
chomp;
print "xxx: $_\n";
}
'
使用字符串文字是最直接的编写方式,但如果Perl脚本本身包含单引号,则不是理想的方法。
perl -e
#/bin/bash
script=$(cat <<'EOF'
while(<>) {
chomp;
print "xxx: $_\n";
}
EOF
)
perl -e "$script"
如果你使用perl -e
将脚本传递给Perl,则不会有stdin问题,并且你可以在脚本中使用任何字符。但是,这种方法有些绕弯子。Here-docs生成stdin上的输入,但我们需要字符串。怎么办?哦,我知道了!这就需要用到$(cat <<HEREDOC)
。
确保使用<<'EOF'
而不仅仅是<<EOF
,以防止bash在这里文档内进行变量插值。
你也可以不使用$script
变量来编写这个脚本,不过现在已经变得非常复杂了!
perl -e "$(cat <<'EOF'
while(<>) {
chomp;
print "xxx: $_\n";
}
EOF
)"
perl <(cat <<'EOF'
while(<>) {
chomp;
print "xxx: $_\n";
}
EOF
)
在第二条线上,您可以使用称为“进程替换”的bash功能,它允许您在文件名的位置编写<(cmd)
。如果您使用此选项,您就不需要-e
,因为您现在传递给perl的是一个文件名而不是字符串。
$_
被shell进行了插值,可能会变成一个空字符串。请对其进行转义... print "xxx: \$_\n";
- mob-x
标志可以产生较少的丑陋结果。 - tjdheredoc
,可以在Perl代码中使用Bash的变量吗? - user3905644您知道吗,我从未考虑过这个问题。
答案是“是的!”,它确实有效。正如其他人所提到的,无法使用<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中,如果你用单引号将Here文档字符串括起来,那么该Here文档就不会被Shell插值。
仅对@John Kugelman的答案进行小修正。您可以消除无用的cat
并使用:
read -r -d '' perlscript <<'EOF'
while(<>) {
chomp;
print "xxx: $_\n";
}
EOF
perl -e "$perlscript"
#!/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
perl -we
? - TLP