map和grep如何工作?

rod*_*dee -5 perl

我在脚本中碰到这个代码来了,能否请您解释一下map,并grep在这里呢?

open FILE, '<', $file or die "Can't open file $file: $!\n";
my @sets = map {
                  chomp;
                  $_ =~ m/use (\w+)/;
                  $1;
                }
grep /^use/, ( <FILE> );

close FILE;
Run Code Online (Sandbox Code Playgroud)

指向的文件$file有:

use set_marvel;
use set_caprion;
and so on...
Run Code Online (Sandbox Code Playgroud)

Mat*_*cob 6

尽管您的问题没有显示出任何研究成果,但无论如何我都会回答它,因为它可能对未来的读者有所帮助.

的perldoc,map:

计算LIST的每个元素的BLOCK或EXPR(对每个元素进行本地设置 $_)并返回由每个这样的评估的结果组成的列表值.在标量上下文中,返回如此生成的元素总数.在列表上下文中计算BLOCK或EXPR,因此LIST的每个元素可以在返回值中生成零个,一个或多个元素.

定义grep,在另一方面:

为LIST的每个元素(对每个元素进行本地设置$_)计算BLOCK或EXPR, 并返回由表达式求值为true的元素组成的列表值.在标量上下文中,返回表达式为true的次数.

因此,它们的输入值,返回值以及它们都是本地化的事实相似$_.

在您的特定代码中,从右到左:

  • <FILE>玷污文件FILE句柄指向的文件中的行并返回一个列表
  • 在上下文中grep,/^use/查看每一行并返回与正则表达式匹配的行.grep因此,返回值是以列表开头的行列表use.
  • 在您的BLOCK中map(仅考虑通过早期grep测试的行):
    • chomp从中删除任何尾随字符串$_对应于当前值$/(即换行符).这是不必要的,因为正如您将在下面看到的,\w永远不会匹配换行符.
    • $_ =~ m/use (\w+)/是一个正则表达式,查找use后跟空格,后跟[0-9a-zA-Z_]捕获组中的一个或多个单词字符().这$_ =~是多余的,因为匹配运算符默认m//绑定$_.
    • $1是前一个表达式中第一个匹配的捕获组.因为它是BLOCK中的最后一个表达式,所以它会作为评估的每个列表项的返回值冒泡.
  • 最终结果存储在一个名为的数组中@sets,该数组应该包含'set_marvel', 'set_caprion', etc.

同样地,你的代码可以在不被改写map,并grep像这样,这可能使你更容易理解:

my @sets;

while (<FILE>) {
    next unless /^use (\w+)/;
    push(@sets, $1);
}
Run Code Online (Sandbox Code Playgroud)