Perl 使用通过Filehandle和while循环定义的

Perl 使用通过Filehandle和while循环定义的,perl,while-loop,filehandle,Perl,While Loop,Filehandle,在阅读一本关于高级Perl编程的书(1)时,我偶然发现 此代码: while (defined($s = <>)) { ... while(已定义($s=)){ ... 在这里使用定义的有什么特殊原因吗 在这些循环构造中,指定的值(无论是否指定 然后测试它是否已定义 定义的测试避免了行中有字符串值的问题 Perl将其视为false,例如不带尾随的“或“0” 如果你真的想让这些值终止循环,它们 应明确测试:[……] 那么,会不会有一个角落的情况,或者仅仅是因为这本书太旧了

在阅读一本关于高级Perl编程的书(1)时,我偶然发现 此代码:

while (defined($s = <>)) {
    ...
while(已定义($s=)){
...
在这里使用
定义的
有什么特殊原因吗

在这些循环构造中,指定的值(无论是否指定 然后测试它是否已定义 定义的测试避免了行中有字符串值的问题 Perl将其视为false,例如不带尾随的
“0”
如果你真的想让这些值终止循环,它们 应明确测试:[……]

那么,会不会有一个角落的情况,或者仅仅是因为这本书太旧了 在最近的Perl版本中添加了自动
定义的
测试


(1) 高级Perl编程,第一版,Sriram Srinivasan.O'Reilly (1997)

while($line=){
chomp($line);
如果(***定义***$行){
打印“请参阅:$line\n”;
}
}
__资料__
1.
0
3.

尝试删除已定义的代码,您将看到不同的结果。

Perl有很多隐式行为,比大多数其他语言都多。Perl的座右铭是有不止一种方法可以做到这一点,而且因为有这么多隐式行为,所以通常有不止一种方法来表达完全相同的事情

/foo/
而不是
$\u=~ m/foo/

$x=shift
而不是
$x=shift@

while(已定义($)
而不是
while()

等等

使用哪种表达方式在很大程度上取决于您当地的编码标准和个人偏好。更明确的表达方式会提醒读者幕后到底发生了什么。这可能会提高代码的可读性,也可能不会提高代码的可读性——这取决于观众的知识水平以及您是否使用了著名的习惯用法。

在这种情况下,隐式行为比看起来要复杂一些。有时
perl
会隐式地对readline运算符的结果执行
定义的(…)
测试:

$ perl -MO=Deparse -e 'while($s=<>) { print $s }'
while (defined($s = <ARGV>)) {
    print $s;
}
-e syntax OK
$perl-MO=Deparse-e'while($s=){print$s}'
while(已定义($s=)){
打印$s;
}
-e语法正常
但有时它不会:

$ perl -MO=Deparse -e 'if($s=<>) { print $s }'
if ($s = <ARGV>) {
    print $s;
}
-e syntax OK

$ perl -MO=Deparse -e 'while(some_condition() && ($s=<>)) { print $s }'
while (some_condition() and $s = <ARGV>) {
    print $s;
}
-e syntax OK
$perl-MO=Deparse-e'if($s=){print$s}
如果($s=){
打印$s;
}
-e语法正常
$perl-MO=Deparse-e'while(some_condition()&($s=){print$s}'
while(一些条件()和$s=){
打印$s;
}
-e语法正常
假设您关心这个隐式行为应该处理的一些极端情况。您是否已将
perlop
提交给内存,以便您了解Perl何时使用这个隐式行为以及何时不使用这个隐式行为?您是否了解Perl v5.14和Perl v5.6之间在这个行为上的差异?阅读Perl v5.14的人是否会这样做我们的代码明白了吗


同样,关于何时使用更显式的表达式,没有正确或错误的答案,但当隐式行为更为深奥时,使用显式表达式的情况更为明显。

假设您有以下文件

4<LF>
3<LF>
2<LF>
1<LF>
0
请注意缺少
0
,因为字符串
0
为false。在不太可能的情况下,需要定义

  • 您有一个非标准文本文件(缺少尾随换行符)
  • 文件的最后一行由单个ASCII零(0x30)组成

但是等一下!如果您实际使用上述数据运行上述代码,您将看到
0
打印出来!许多人不知道的是Perl自动转换

while ($s = <>) {

我知道这会有所不同,但事实并非如此。问题是在循环条件中使用
defined
。-1表示不回答问题和提供非编译代码。Perl自动将
while($line=)
替换为
while(defined($line=))
,因此如果您看到的是不同的东西,那么您显然是在谈论与OP不同的东西。(请参阅
perl-MO=Deparse-e'while($line=){}'
的输出)我还注意到,实际问题的答案被埋藏在最后一段中。很明显,当代码> /fo/</代码>意味着<代码> $y~~/fo/</代码>时,但当<>代码> <代码>意味着<代码>定义($y=)<代码>时,几乎不清楚。我不认为它们是相同的。
while ($s = <>) {
   chomp;
   say $s;
}
4
3
2
1
while ($s = <>) {
while (defined($s = <>)) {
$ perl -MO=Deparse -e'while($s=<DATA>) {}'
while (defined($s = <DATA>)) {
    ();
}
__DATA__
-e syntax OK
$ perl -MO=Deparse -e'while((), $s=<DATA>) {}'
while ((), $s = <DATA>) {
    ();
}
__DATA__
-e syntax OK