如何使数组中的 STDIN 停止? (PERL)

How do I make the STDIN in the Array stop? (PERL)

我的@array 不会停止接收 STDIN...

my @array = undef;
while (@array = undef){
    @array = <STDIN>;
    for (@array[x]=5){
        @array = defined;
    }
}

如前所述,将 STDIN 限制为五行

use warnings;
use strict;
use feature 'say';

my @input;

while (<STDIN>) {
    chomp;
    push @input, $_;
    last if @input == 5;
}

say for @input;

在发布的代码中还有其他要评论的地方。当从文件句柄读取时,, I'd like to address the business of context 中详细清除了很多内容。

"diamond" 运算符 <> 是上下文感知的。来自 I/O Operators (perlop)

If a <FILEHANDLE> is used in a context that is looking for a list, a list comprising all input lines is returned, one line per list element. It's easy to grow to a rather large data space this way, so use with care.

在通常的 while 循环中,<> 在标量上下文中

while (my $line = <$fh>)

它与 while (<$fh>) 相同,因为它默认分配给 $_ variable,一个标量。

但是如果我们分配给一个数组,比如从打开文件的文件句柄$fh

my @lines = <$fh>;

then <> 运算符在列表上下文中工作。它读取所有行直到它看到 EOF(文件结尾),此时它 returns 所有行,这些行被分配给 @lines。请记住,每一行都有其换行符。您可以通过

将它们全部删除
chomp @lines;

因为 chomp 也适用于列表。

使用 STDIN 当输入来自键盘时会引发问题,因为 <> 等待更多输入,因为 EOF 不会自行出现。它通常在 Unixy 系统上以 Ctrl+D 给出(在 Windows 上按 Ctrl+Z)。

因此,原则上您可以使用 @array = <STDIN> 并使用 Ctrl+D 退出输入,但这对于预期的键盘输入可能有点尴尬,因为它主要意味着需要逐行输入加工。如果 STDIN 来自文件,

则不太常见
script.pl < input.txt

或命令行上的管道

some command with output | script.pl

我们确实得到了 EOF(由 EOT 提供)。

但是我在阅读STDIN的时候还是会坚持一个习惯while,逐行处理。


Ctrl+D 通常是这样称呼的,但实际上是用 Ctrl 键入小写的 d。请注意,Ctrlc(标记为 Ctrl+C)做的事情完全不同;它发送 SIGINT 信号,如果没有被捕获则终止整个程序。

my @array = undef;
while (@array = undef){

这两行不做(我假设)你认为他们正在做的事情。

my @array = undef;

这定义了一个数组,其中只有一个元素是特殊值 undef。我怀疑你真正想要的是:

my @array = ();

创建一个空数组。但是 Perl 数组在第一次创建时总是空的,所以这可以简化为:

my @array;

第二行重复该错误并添加一个新错误。

while (@array = undef) {

我怀疑你想在这里检查一个空数组并且你正在寻找类似于“if @array is undefined”的东西。但是你错过了一个事实,即在 Perl 中,赋值运算符(如 =) 与比较运算符(如 ==)不同。所以这一行 undef 赋值给 @array 而不是比较它。你真的想要 @array == undef - 但那也不对。

您需要摒弃这种检查数组是否为 "defined" 的想法。您真正感兴趣的是数组是否为空。 Perl 有一个聪明的技巧可以帮助您解决这个问题。

如果您在 Perl 希望看到单个(标量)值的地方使用 Perl 数组,它会为您提供数组中元素的数量。所以你可以这样写代码:

my $number_of_elements = @an_array;

ifwhile 条件中的布尔逻辑检查是单个标量值。所以如果你想检查一个数组是否包含任何元素,你可以使用这样的代码:

if (@array) {
  # @array contains data
} else {
  # @array is empty
}

当数组包含元素时循环,你可以简单地写:

while (@array) {
  # do something
}

但是在这里,您想在数组为空时执行某些操作。为此,您可以反转 while 条件逻辑(对 "not" 使用 !):

while (!@array) {
  # do something
}

或者您可以切换到使用 until 测试(与 while 相反):

until (@array) {
  # do something
}

我要到此为止了。我希望这能让您深入了解您的代码有什么问题。恐怕这种程度的错误也会渗透到您的其余代码中。