Perl映射块本地变量用法

时间:2011-05-19 07:19:25

标签: perl map implicit local-variables

此代码通过一组路径中唯一的basename存根的哈希键来编译集合。

%stubs = map { $f=basename $_; $f =~ /^([A-Za-z]+[0-9]+)\./ ; $1=>() } @pathlist;

为什么我需要$f引用?我以为我会好的:

%stubs = map { basename; /^([A-Za-z]+[0-9]+)\./; $1=>() } @pathlist;

但我没有比赛。我不允许在地图块中修改$ _吗?



对于那些想知道代码在做什么的人:

对于每个$ path(@pathlist),它获取basename,匹配第一个字母数字序列,然后返回第一个括号匹配作为空列表值的键。例如:

/some/dir/foo123.adfjijoijb
/some/dir/foo123.oibhobihe
/some/dir/bar789.popjpoj

返回

foo123 => ()
bar789 => ()

之后我使用地图的键作为一组值进行处理。

3 个答案:

答案 0 :(得分:13)

basename不默认代理$_。但是你可以匹配它的返回值,而不是使用$ f:

%stubs = map { basename($_) =~ /^([A-Za-z]+[0-9]+)\./; $1 => undef } @pathlist;

注意列表中的()不会产生元素,它只会变平为零;你必须提供一个价值,即使只是undef。使用$1 => (),映射迭代将交替生成密钥和%stubs的值。

在使用$ 1之前总是检查你的正则表达式是否成功是好的:

%stubs = map { basename($_) =~ /^([A-Za-z]+[0-9]+)\./ ? ($1 => undef) : () } @pathlist;

虽然如果你不介意哈希值是空字符串而不是undef,你可以让正则表达式匹配返回所需的列表:

%stubs = map { basename($_) =~ /^([A-Za-z]+[0-9]+)()\./ } @pathlist;

答案 1 :(得分:6)

在map和grep中,$ _是数组中值的别名。如果修改它们,实际上是修改数组中的值。这可能不是你想要的,可能是出了什么问题,但是在这两种情况下调试打印键%stubs和@pathlist,让我们知道它的内容。

另外:File :: Basename的basename不会隐式处理$ _。它会给我带来错误。

#!/usr/bin/perl
use feature say;
use File::Basename;

@pathlist=("/some/dir/foo123.adfjijoijb","/some/dir/foo123.oibhobihe","/some/dir/bar789.popjpoj");
%stubs1 = map { $f=basename $_; $f =~ /^([A-Za-z]+[0-9]+)\./ ; $1=>() } @pathlist;
say join(',',keys %stubs1);
say "---";
say join(',',@pathlist);
say "---";

%stubs = map { $_=basename $_; /^([A-Za-z]+[0-9]+)\./; $1=>() } @pathlist;
say join(',',keys %stubs);
say "---";
say join(',',@pathlist);
say "---";

%stubs = map {basename; /^([A-Za-z]+[0-9]+)\./; $1=>() } @pathlist;

答案 2 :(得分:0)

替代实施:

my %stubs =
   map { $_ => undef }
   map { basename($_) =~ /^([A-Za-z]+[0-9]+)\./ }
   @pathlist;