我写的代码如下:
#!/usr/bin/perl 
my @input = ( "a.txt" , "b.txt" , "c.txt" ) ;
my @output = map { $_ =~ s/\..*$// } @input ;
print @output ;
我的目的是让没有扩展名的文件名存储在数组中@output.但它改为存储返回的值s///而不是更改的文件名@output,因此结果如下
1
1
1
那么map在这种情况下使用的正确方法是什么?
bri*_*foy 19
在所有这些答案中,没有人只是说map返回最后一个评估表达式的结果.无论你最后做什么,事情(或事物)都会map回归.它就像一个子程序或do返回结果的最后一个计算表达式.
Perl v5.14添加了非破坏性替换,我在使用/ r替换标志来处理副本.它不返回替换次数,而是返回修改后的副本.使用/r标志:
my @output = map { s/\..*$//r } @input;
请注意,您不需要使用$_绑定运算符,因为这是默认主题.
der*_*ert 16
好的,首先,您可能想要$_ =~ s/\..*$//- 请注意s您的示例中缺少的内容.另外,你可能map不是grep.
其次,这不符合你的要求.这实际上是修改@input!内部grep(以及map其他几个地方)$_实际上是每个值的别名.所以你实际上是在改变价值.
另请注意,模式匹配不会返回匹配的值; 它返回true(如果有匹配)或false(如果没有).这就是你所看到的所有1.
相反,做这样的事情:
my @output = map {
    (my $foo = $_) =~ s/\..*$//;
    $foo;
} @input ;
第一个复制$_到$foo,然后修改$foo.然后,它返回修改后的值(存储在其中$foo).你不能使用return $foo,因为它是一个块,而不是子程序.
$_已经讨论了列表值的别名问题.
但更重要的是:你的问题的标题清楚地说"地图",但你的代码使用grep,虽然它看起来真的应该使用map.
grep将评估您提供的列表中的每个元素作为第二个参数.在列表上下文中,它将返回一个列表,该列表包含表达式返回true的原始列表的那些元素.
map 另一方面,使用表达式或块参数来转换list参数的元素,返回一个新的列表,该列表由原始的转换参数组成. 
因此,您的问题可以通过以下代码解决:
@output = map { m/(.+)\.[^\.]+/ ? $1 : $_ } @input;
这将匹配不是扩展名的文件名部分,并作为评估结果返回,如果没有扩展名,则返回原始名称.