What's the most defensive way to loop through lines in a file with Perl?

前端 未结 3 1703
粉色の甜心
粉色の甜心 2021-01-01 22:14

I usually loop through lines in a file using the following code:

open my $fh, \'<\', $file or die \"Could not open file $file for reading: $!\\n\";
while          


        
3条回答
  •  一生所求
    2021-01-01 22:38

    BTW, this is covered in the I/O Operators section of perldoc perlop:

    In scalar context, evaluating a filehandle in angle brackets yields the next line from that file (the newline, if any, included), or "undef" at end-of-file or on error. When $/ is set to "undef" (sometimes known as file-slurp mode) and the file is empty, it returns '' the first time, followed by "undef" subsequently.

    Ordinarily you must assign the returned value to a variable, but there is one situation where an automatic assignment happens. If and only if the input symbol is the only thing inside the conditional of a "while" statement (even if disguised as a "for(;;)" loop), the value is automatically assigned to the global variable $_, destroying whatever was there previously. (This may seem like an odd thing to you, but you'll use the construct in almost every Perl script you write.) The $_ variable is not implicitly localized. You'll have to put a "local $_;" before the loop if you want that to happen.

    The following lines are equivalent:

    while (defined($_ = )) { print; }
    while ($_ = ) { print; }
    while () { print; }
    for (;;) { print; }
    print while defined($_ = );
    print while ($_ = );
    print while ;
    

    This also behaves similarly, but avoids $_ :

    while (my $line = ) { print $line }
    

    In these loop constructs, the assigned value (whether assignment is automatic or explicit) is then tested to see whether it is defined. The defined test avoids problems where line has a string value that would be treated as false by Perl, for example a "" or a "0" with no trailing newline. If you really mean for such values to terminate the loop, they should be tested for explicitly:

    while (($_ = ) ne '0') { ... }
    while () { last unless $_; ... }
    

    In other boolean contexts, "" without an explicit "defined" test or comparison elicit a warning if the "use warnings" pragma or the -w command-line switch (the $^W variable) is in effect.

提交回复
热议问题