您对foreach 中的print 的问题已得到解答,这里有更多关于$_ 的内容。
来自General Variables in perlvar
下面是 Perl 假定 $_ 的地方,即使你不使用它:
-
以下函数使用$_ 作为默认参数:
- abs、alarm、chomp、chop、chr、chroot、cos、defined、eval、evalbytes、exp、fc、glob、hex、int、lc、lcfirst、长度、log、lstat、mkdir、oct、ord、pos , print, printf, quotemeta, readlink, readpipe, ref, require, reverse (仅在标量上下文中), rmdir, say, sin, split (第二个参数), sqrt, stat, study, uc, ucfirst, unlink, unpack .
所有文件测试(-f,-d)除了 -t,默认为 STDIN。见-X
模式匹配操作m//、s/// 和tr///(又名y///)在没有=~ 运算符的情况下使用。
foreach 循环中的默认迭代器变量(如果没有提供其他变量)。
grep() 和 map() 函数中的隐式迭代器变量。
given()的隐式变量。
当<FH>、readline、readdir 或each 操作的结果作为while 测试的唯一标准自行测试时,放置下一个值或输入记录的默认位置.在while 测试之外,这不会发生。
$_ 默认为全局变量。
如您所见,它几乎随处可用,而且确实被大量使用。请注意,perlvar 页面描述了更多类似的变量,其中许多值得了解。
这是一个例子。考虑到我们从文件中读取行,想要丢弃只有空格或以# (cmets) 开头的行,而其他人希望将它们按空格拆分为单词。
open my $fh, '<', $file or die "Can't open $file: $!";
while (<$fh>)
{
next if not /\S/;
next if /^\s*#/;
my @words = split;
# do something with @words ...
}
让我们看看上面的例子中有多少$_ 的用法。这是一个等效的程序
while (my $line = <$fh>)
{
next if not $line =~ m/\S/; # if not matching any non-space character
next if $line =~ m/^\s*#/; # if matching # after only (possible) spaces
my @words = split ' ', $line; # split $line by ' ' (any white space)
# do something with @words ...
}
比较这两个
while 条件中读取的文件句柄 <$fh> 分配给 $_,然后在循环中可用。
正则表达式的匹配操作符默认作用于$_。 m 本身可以被删除。
split 默认拆分 $_。我们还使用另一个默认值,用于分割字符串的模式,即' '(任何数量的任何空白)。
一旦我们使用$line = <$fh>,与$_ 的交易就关闭了(它在循环中未定义),我们必须在任何地方使用$line。所以要么执行此操作或执行while (<$fh>)并使用$_。
为了进一步说明这一切,让我们找出每一行中最长的大写单词
use List::Util 'max';
my $longest_cap = max map { length } grep { /^[A-Z]/ } @words;
grep 获取@words 中的列表并将块应用于每个元素。每个元素都分配给$_,因此块内的代码可以使用$_。这是正则表达式默认使用的。满足条件的那些被传递给map,它还会迭代地将它们分配给$_,这当然是length的默认值。最后,max 从List::Util 中选出最大的一个。
请注意,$_ 从未实际写入,也不需要临时变量。
这里是一些相关文档。 I/O Operators in perlop 讨论 while (<$fh>) 和所有相关的事情。正则表达式部分位于Regexp Quote-Like Operators in perlop 和perlretut 中。也看看split。
默认值经常被使用,并且要阅读其他人编写的代码,您必须了解它们。当你编写你自己的代码时,你可以选择是否使用$_,因为总是可以引入一个词法变量来代替它。
那么,什么时候默认使用$_(不需要写),什么时候不使用?
正确使用默认值,尤其是$_,可以生成更清晰、更易读的代码。通常意味着更好的代码。但很有可能将其推得太远,最终导致代码晦涩、棘手和脆弱。所以味道好是必须的。
另一种情况是代码的某些部分受益于将$_ 作为默认值,而在其他地方则必须显式使用$_。我想说如果$_ 在一段代码中出现不止一次或两次,这意味着应该有一个正确命名的变量。
总的来说,如果有疑问,只需简单地命名所有内容。