I'm performing a test and need to assign a specific value to STDIN within a perl code.
So instead of reading from stdin like this:
#myperl.pl
#!//usr/bin/env perl
#
while (<>) {
print;
}
# echo hello | ./myperl.pl
hello
I can just do this:
#myperl.pl
#!//usr/bin/env perl
#
<STDIN> = "hello";
while (<>) {
print;
}
./myperl.pl
# hello
Of course, the text hello
can be multiple lines in a real test case scenario.
According to perldoc open
:
[...] you can open filehandles directly to Perl scalars via:
open(my $fh, ">", \$variable) || ..
see also PerlIO::scalar. Further, according to perldoc perlop:
The null filehandle <> is special: it can be used to emulate the behavior of
sed
andawk
, and any other Unix filter program that takes a list of filenames, doing the same to each line of input from all of them. Input from<>
comes either from standard input, or from each file listed on the command line. Here's how it works: the first time<>
is evaluated, the@ARGV
array is checked, and if it is empty,$ARGV[0]
is set to"-"
, which when opened gives you standard input. The@ARGV
array is then processed as a list of filenames.
So when you do while (<>)
it will try to "open standard input" (provided you did not give command line arguments, i.e. @ARGV
is empty). This open
command is not affected by the current value of the variable STDIN
, instead (I guess) it will simply do something like:
open ARGV, '/dev/tty' or die "open: /dev/tty: $!";
So it seems it is not possible to redefine the behavior of <>
to read from a string by changing STDIN
.
But instead of using the null file handle <>
in your loop, if you could use <STDIN>
instead.. then redefining STDIN
to a string file handle would work:
use strict;
use warnings;
my $str = "hello\n";
open my $fh, "<", \$str or die "Could not open string file handle: $!";
{
local *STDIN = $fh;
while (<STDIN>) {
print;
}
}
close $fh;
my $line = <STDIN>;
print "Terminal input: ", $line;
Edit:
The following also seems to work:
local *ARGV = $fh;
while (<>) {
print;
}