if(!$_) 的含义

Meaning of if(!$_)

我有一个正在读取文件的 Perl 脚本。在某些时候,代码在 for 循环中使用以下 if 语句:

for (my $i = 0; $i<10 ; $i++ ) {

    $_ = <INPUT>;
    if (!$_) {last;} 
    
...

我是 Perl 新手,所以我想知道 !$_ 的含义。在这个例子中,$_ 是我文件的一行。那么,如果语句为真,该行应该包含哪些内容。

if 条件,即 () 中的内容,在 boolean scalar context 中进行评估以测试“真实性”。因此,如果它是 undef''(空字符串)或 0(或字符串 "0")则为假。

! 否定其后的内容,因此如果 $_ 为假(undef''0,则 if (!$_) 为真或 "0")。但是,在这种情况下,$_ 是从 <> operator 分配的,所以它总是在末尾有一个换行符——除非 <> 的源已经耗尽,在这种情况下 <> returns undef.

因此,在这种情况下,if (!$_) 测试是否没有更多内容可从 INPUT 读取,如果是,则使用 last 退出 for 循环是这样的。

对显示的代码的一些评论。

  • 那个 C 风格的 for 循环也可以写成 for my $i (0..9),这被认为更好,更易读。 参见 foreach, and really follow links for flow-control key-words

  • 这段代码

    $_=<INPUT>
    if (!$_) { last; }
    ...
    

    INPUT 文件句柄读取并在文件结束时退出其循环(参见 last)。 (这不必是实际文件,而是可通过文件句柄读取的任何资源。)

    这至少可以说是笨拙的;一种常见的做法是

    while (<INPUT>) {
        ...
    }
    

如此之多,以至于即使是硬核编译语言现在也拥有它。 C++11引入了range-based for loop

for (auto var: container) ...  // (really, const auto&), or auto&, or auto&&

上面链接的标准参考说

Used as a more readable equivalent to the traditional for loop [...]