为 perl STDIN 分配特定值

assign specific value to perl STDIN

我正在执行测试,需要在 perl 代码中为 STDIN 分配一个特定值。

所以不要像这样从 stdin 读取:

#myperl.pl
#!//usr/bin/env perl
#
while (<>) {
print;
}

# echo hello | ./myperl.pl
hello

我只能这样做:

#myperl.pl
#!//usr/bin/env perl
#
<STDIN> = "hello";
while (<>) {
print;
}

./myperl.pl
# hello

当然,在真实的测试用例场景中,文本hello可以是多行。

根据perldoc open

[...] you can open filehandles directly to Perl scalars via:

open(my $fh, ">", $variable) || ..   

另见 PerlIO::scalar. Further, according to perldoc perlop:

The null filehandle <> is special: it can be used to emulate the behavior of sed and awk, 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.

所以当你做 while (<>) 时,它会尝试 "open standard input"(前提是你没有给出命令行参数,即 @ARGV 是空的)。这个 open 命令不受变量 STDIN 当前值的影响,相反(我猜)它只会做类似的事情:

open ARGV, '/dev/tty' or die "open: /dev/tty: $!";

所以似乎无法通过更改 STDIN.

来重新定义 <> 的行为以从字符串中读取

但是,如果您可以使用 <STDIN>,而不是在循环中使用空文件句柄 <>,那么将 STDIN 重新定义为字符串文件句柄就可以了:

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;

编辑

以下似乎也有效:

local *ARGV = $fh;
while (<>) {
    print;
}