map和grep如何工作?

时间:2016-01-21 22:47:50

标签: perl

我在脚本中遇到了这段代码,您能解释一下mapgrep在这里做了什么吗?

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

close FILE;

$file指向的文件包含:

use set_marvel;
use set_caprion;
and so on...

2 个答案:

答案 0 :(得分:6)

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

根据perldocmap

  

评估LIST的每个元素的BLOCK或EXPR(本地设置   $_到每个元素)并返回由结果组成的列表值   每次这样的评估。在标量上下文中,返回总数   这样生成的元素。在列表上下文中评估BLOCK或EXPR,所以   LIST的每个元素可以产生零个,一个或多个元素   返回值。

grep definition,另一方面:

  

评估LIST的每个元素的BLOCK或EXPR(本地设置   $_到每个元素)并返回由这些元素组成的列表值   表达式求值为true的元素。在标量中   context,返回表达式为真的次数。

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

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

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

同样地,您的代码可以在没有mapgrep的情况下重写,这可能会让您更容易理解:

my @sets;

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

答案 1 :(得分:0)

grep<FILE>作为输入,并使用正则表达式^use将所有以use开头的行复制到传递给{的数组中{1}}。

map循环遍历每个数组条目,并将每个条目放入map,然后隐式调用$_上的chomp。然后$_在$ _上执行正则表达式,捕获$_ =~ m/use (\w+)/;后面的单词并将其放入use。然后调用$1将其放入$1