Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl inside Bash: How to read from pipe and pass arguments to perl at the same time?

Following is the code I am trying out:

echo "a b c" | perl -e 'print $ARGV[0]; print $ARGV[1]; print $_;' "abc" "def"

Output of this code is:

abcdef

I am not able to figure out why "print $_;" is not printing "a b c" as usual. Any ideas?

like image 710
vervenumen Avatar asked Dec 20 '22 08:12

vervenumen


1 Answers

You are not using -n or -p, so you are not using <> for standard input. Which you would not do anyway if you have arguments.

Explanation:

When you use -n or -p, it puts a while(<>) loop around your code, like so:

perl -ne ' print ' 

is equal to

perl -e ' while (<>) { print }'

And if you use -p it is:

perl -e ' while (<>) { print } continue { print $_ }'

At this stage, Perl will decide how <> will work by checking @ARGV, where the arguments to the script are stored. If there is anything in there, it will treat the arguments as file names, and try to open and read these files. The file handle will then be called ARGV. At this point, <> cannot be used to read from standard input.

Solution

In other words, using arguments will override the reading from STDIN. So if you want to read from standard input, you use that file handle instead:

echo "a b c" | perl -e ' print @ARGV[0,1]; while (<STDIN>) { print } ' foo bar

Another option would be to clear the @ARGV array beforehand, like so:

echo "a b c"|perl -ne'BEGIN { @x = @ARGV; @ARGV = () }; print @x; print;' foo bar

But that would also print @x one time per line of input you have, which may not be desirable.

like image 141
TLP Avatar answered Jan 10 '23 07:01

TLP