Perl script в bash HereDoc
Возможно ли несколько написать perl script в bash script как heredoc?
Это не работает (только пример)
#/bin/bash
perl <<EOF
while(<>) {
chomp;
print "xxx: $_\n";
}
EOF
Вот какой хороший способ встроить perl script в bash script? Хотите запустить perl script из bash script и не хотите помещать его во внешний файл.
Ответы
Ответ 1
Проблема здесь в том, что script передается perl на stdin, поэтому попытка обработки stdin из script не работает.
1. Строковый литерал
perl -e '
while(<>) {
chomp;
print "xxx: $_\n";
}
'
Использование строкового литерала - самый прямой способ написать это, хотя это не идеально, если Perl script содержит одиночные кавычки.
2. Используйте perl -e
#/bin/bash
script=$(cat <<'EOF'
while(<>) {
chomp;
print "xxx: $_\n";
}
EOF
)
perl -e "$script"
Если вы передаете script в perl с помощью perl -e
, тогда у вас не будет проблемы с stdin, и вы можете использовать любые символы, которые вам нравятся в script. Тем не менее, это немного круто. 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)
писать <(cmd)
. Если вы используете это, вам не нужен -e
, поскольку теперь вы передаете perl имя файла, а не строку.
Ответ 2
Только маленькое подразделение @Джона Кугельмана ответит. Вы можете устранить бесполезный cat
и использовать:
read -r -d '' perlscript <<'EOF'
while(<>) {
chomp;
print "xxx: $_\n";
}
EOF
perl -e "$perlscript"
Ответ 3
Знаешь, я никогда не думал об этом.
Ответ: YES!, он работает. Как уже упоминалось, <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, если вы окружите конец этой строки документа одинарными кавычками, здесь документ не интерполируется оболочкой.
Ответ 4
Вот еще один способ использования PERL HEREDOC script в пределах bash и в полной мере использовать его.
#!/bin/sh
#If you are not passing bash var 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 $ 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