Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl script in bash's HereDoc

Tags:

bash

perl

Is possible somewhat write a perl script in a bash script as heredoc?

This is not working (example only)

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

Is here some nice way how to embed a perl script into a bash script? Want run perl script from an bash script and don't want put it into external file.

like image 383
jm666 Avatar asked Jul 19 '13 16:07

jm666


3 Answers

The problem here is that the script is being passed to perl on stdin, so trying to process stdin from the script doesn't work.

1. String literal

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

Using a string literal is the most direct way to write this, though it's not ideal if the Perl script contains single quotes itself.

2. Use perl -e

#/bin/bash

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

If you pass the script to perl using perl -e then you won't have the stdin problem and you can use any characters you like in the script. It's a bit roundabout to do this, though. Heredocs yield input on stdin and we need strings. What to do? Oh, I know! This calls for $(cat <<HEREDOC).

Make sure to use <<'EOF' rather than just <<EOF to keep bash from doing variable interpolation inside the heredoc.

You could also write this without the $script variable, although it's getting awfully hairy now!

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

3. Process substitution

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

Along the lines of #2, you can use a bash feature called process substitution which lets you write <(cmd) in place of a file name. If you use this you don't need the -e since you're now passing perl a file name rather than a string.

like image 192
John Kugelman Avatar answered Nov 06 '22 23:11

John Kugelman


You know I never thought of this.

The answer is "YES!" it does work. As others have mentioned, <STDIN> can't be used, but this worked fine:

$ 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

In Kornshell and in BASH, if you surround your end of here document string with single quotes, the here document isn't interpolated by the shell.

like image 31
David W. Avatar answered Nov 06 '22 23:11

David W.


Only small corection of @John Kugelman's answer. You can eliminate the useless cat and use:

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

perl -e "$perlscript"
like image 2
jm666 Avatar answered Nov 07 '22 00:11

jm666