我在脚本中遇到了这段代码,您能解释一下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;
$file
指向的文件包含:
use set_marvel;
use set_caprion;
and so on...
答案 0 :(得分:6)
尽管您的问题没有显示出任何研究成果,但无论如何我都会回答它,因为它可能会对未来的读者产生帮助。
根据perldoc,map
:
评估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.
同样地,您的代码可以在没有map
和grep
的情况下重写,这可能会让您更容易理解:
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
。