【问题标题】:How are the values printed in the foreach statement?foreach 语句中的值是如何打印的?
【发布时间】:2017-01-21 10:26:32
【问题描述】:

我对 perl 编程非常陌生。

在阅读循环时,对于 foreach 循环,我得到了两个示例。

一个例子是,

foreach ('hickory','dickory','doc') {
   print $_;
   print "\n";
}

输出:-

hickory
dickory
doc

$_ 变量包含每个项目。所以,它会打印出来。

在另一个例子中,他们说没有在 print 语句中指定 $_ 变量。空的打印语句只在那里。它如何打印 foreach 参数。

foreach ('hickory','dickory','doc') {
   print;
   print "\n";
}

输出:-

hickory
dickory
doc

为此也有相同的输出。它如何打印值。在那本书中,他们没有对此给出任何解释。我在互联网上进行了搜索。但是我什么都找不到。

【问题讨论】:

  • 参见perldoc -f print如果省略 LIST,则将 $_ 打印到当前选定的输出句柄。 $_ 是打印的默认参数,这意味着如果您只是不带参数调用print$_ 被打印出来。
  • General Variables in perlvar 中查看$_。 Perl 中有 许多 项默认使用它,它是 最常见的设备之一。
  • 有人要写答案吗?这是一个有效的问题,尽管阅读文档就足够了。只是找到那个特定的文档很难。上面的cmets我们基本上都有答案了,但是cmets不是用来回答的。我会等待,以防你们中的一个人决定写答案。
  • 所以我做了@simbabque
  • @simbabque 感谢您提示答案,您完全正确。这个问题起初在我看来是文档中的问题,但它确实需要并保证得到正确的答案。

标签: perl foreach


【解决方案1】:

您对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>readlinereaddireach 操作的结果作为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 条件中读取的文件句柄 &lt;$fh&gt; 分配给 $_,然后在循环中可用。

  • 正则表达式的匹配操作符默认作用于$_m 本身可以被删除。

  • split 默认拆分 $_。我们还使用另一个默认值,用于分割字符串的模式,即' '(任何数量的任何空白)。

  • 一旦我们使用$line = &lt;$fh&gt;,与$_ 的交易就关闭了(它在循环中未定义),我们必须在任何地方使用$line。所以要么执行此操作执行while (&lt;$fh&gt;)并使用$_

为了进一步说明这一切,让我们找出每一行中最长的大写单词

use List::Util 'max';

my $longest_cap = max map { length } grep { /^[A-Z]/ } @words;

grep 获取@words 中的列表并将块应用于每个元素。每个元素都分配给$_,因此块内的代码可以使用$_。这是正则表达式默认使用的。满足条件的那些被传递给map,它还会迭代地将它们分配给$_,这当然是length的默认值。最后,maxList::Util 中选出最大的一个。

请注意,$_ 从未实际写入,也不需要临时变量。

这里是一些相关文档。 I/O Operators in perlop 讨论 while (&lt;$fh&gt;) 和所有相关的事情。正则表达式部分位于Regexp Quote-Like Operators in perlopperlretut 中。也看看split


默认值经常被使用,并且要阅读其他人编写的代码,您必须了解它们。当你编写你自己的代码时,你可以选择是否使用$_,因为总是可以引入一个词法变量来代替它。

那么,什么时候默认使用$_(不需要写),什么时候不使用?

正确使用默认值,尤其是$_,可以生成更清晰、更易读的代码。通常意味着更好的代码。但很有可能将其推得太远,最终导致代码晦涩、棘手和脆弱。所以味道好是必须的。

另一种情况是代码的某些部分受益于将$_ 作为默认值,而在其他地方则必须显式使用$_。我想说如果$_ 在一段代码中出现不止一次或两次,这意味着应该有一个正确命名的变量。

总的来说,如果有疑问,只需简单地命名所有内容。

【讨论】:

    【解决方案2】:

    如果您没有在 foreach 循环中声明任何变量,则默认设置为 $_

    来自perldoc about foreach

    foreach 关键字实际上是 for 关键字的同义词,所以你 可以使用任何一个。如果省略 VAR,则将 $_ 设置为每个值。

    所以它解释了第一个循环。

    第二个循环,正如您现在已经知道的那样,$_ 是用数组中的每个元素设置的,它将起作用,因为您省略了 $var

    您可以使用带有显式变量的 foreach 循环,如下所示:

    foreach my $item ( @list )
    {
    
     print "My item is: $item\n";
    
    } 
    

    或者你可以像以前一样省略,print 仍然会像@Dada 所说的那样工作,因为:

    如果省略 FILEHANDLE,则打印到最后选择的位置(参见选择) 输出句柄。如果省略 LIST,则将 $_ 打印到当前选定的 输出句柄。

    【讨论】:

      【解决方案3】:

      我将解释为什么使用不同的语法会得到相同的结果:

      如果从 foreach 的开头省略控制变量 循环,Perl 使用它最喜欢的默认变量 $_ 。这(大部分)就像任何其他标量变量一样,除了它不寻常的名称。例如:

      foreach ('hickory','dickory','doc') {
        print $_;
        print "\n";
      }
      

      输出:

      hickory
      dickory
      doc
      

      虽然这不是 Perl 唯一的默认设置,但它是 Perl 最常见的默认设置。您会看到许多其他情况,在这些情况下,当您不告诉 Perl 使用其他变量或值时,Perl 会自动使用 $_,从而使程序员免于思考和键入新变量名的繁重工作。为了不让您感到悬念,其中一种情况是 print ,如果没有给出其他参数,它将打印 $_:

      foreach ('hickory','dickory','doc') {
        print; # prints $_ by default
        print "\n";
      }
      

      输出:-

      hickory
      dickory
      doc
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-13
        • 1970-01-01
        • 1970-01-01
        • 2010-10-19
        相关资源
        最近更新 更多