Подтвердить что ты не робот

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 и не хотите помещать его во внешний файл.

4b9b3361

Ответ 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