有可能在 bash 脚本中写一个 perl 脚本作为 heredoc 吗?
这不起作用(仅示例)
#/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 使用,perl -e
那么您将不会遇到标准输入问题,并且您可以在脚本中使用您喜欢的任何字符。不过,这样做有点迂回。Heredocs 在标准输入上产生输入,我们需要字符串。该怎么办?哦,我知道!这要求$(cat <<HEREDOC)
.
确保使用<<'EOF'
而不是仅仅<<EOF
阻止 bash 在 heredoc 中进行变量插值。
您也可以在没有$script
变量的情况下编写它,尽管它现在变得非常多毛!
perl -e "$(cat <<'EOF'
while(<>) {
chomp;
print "xxx: $_\n";
}
EOF
)"
perl <(cat <<'EOF'
while(<>) {
chomp;
print "xxx: $_\n";
}
EOF
)
沿着 #2 的思路,您可以使用称为进程替换的 bash 功能,它可以让您<(cmd)
代替文件名进行写入。如果你使用它,你就不需要了,-e
因为你现在传递给 perl 的是一个文件名而不是一个字符串。
你知道我从来没有想过这个。
答案是“是的! ”它确实有效。正如其他人所提到的,<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 插入。
只是对@John Kugelman 的回答进行了少量修改。您可以消除无用的cat
并使用:
read -r -d '' perlscript <<'EOF'
while(<>) {
chomp;
print "xxx: $_\n";
}
EOF
perl -e "$perlscript"
这是在 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