2013-07-07 20 views
3

我需要基于正则表达式过滤哈希,如果正则表达式匹配,则从哈希中删除密钥。perl - 通过与匹配正则表达式匹配的密钥匹配而不使用smartmatch

这是我到目前为止,不幸的是它不做任何事情,我不知道为什么。

所以,我建立的正则表达式进行字符串数组,我需要匹配子一样,所以如果哈希关键是someprefix_somestring我需要匹配它somestringstring

my $hashref = {someprefix_somekey => 'somevalue', otherprefix_otherkey => 23, otherprefix_somekey => 'someothervalue'}; 
my @array_of_strings = ('somekey', 'strings', 'bits', 'bobs'); 

my $regex = join('|', sort { length($b) <=> length($a) or $a cmp $b } @array_of_strings); 
$regex = qr{($regex)}; 

delete $hashref->{ grep { !m/$regex/ } keys %$hashref }; 

我期望$hashref看起来像这样算账:{otherprefix_otherkey => 23}因为someprefix_somekeyotherprefix_somekey会匹配$regex,并会因此从散列中删除

我不知道为什么这是不工作请赐教

由于霍布斯回答我能够使它发挥作用,这是我现在有:

my $hashref = {someprefix_somekey => 'somevalue', otherprefix_otherkey => 23, otherprefix_somekey => 'someothervalue'}; 
my @array_of_strings = ('somekey', 'strings', 'bits', 'bobs'); 

my $regex = join('|', sort { length($b) <=> length($a) or $a cmp $b } @array_of_strings); 
$regex = qr{($regex)}; 

delete @{$hashref}{grep { m/$regex/ } keys %$hashref }; 

回答

7

delete是不完全正确,因为你使用的符号来访问一个密钥,因此grep在标量上下文中运行。这意味着如果有三个密钥与您的正则表达式不匹配,最终您会尝试执行类似delete $hashref->{'3'}的操作。

如果你改变你的最后一行到这一点,应该工作:

delete @{$hashref}{grep /$regex/, keys %$hashref }; 

它使用哈希片。如果你认为语法太丑陋了,你也可以

delete $hashref->{$_} for grep /$regex/, keys %$hashref; 

这可能会更自然地阅读一点点。

+2

是的,但OP只想保留不匹配的内容,所以你应该删除grep可以找到的所有条目,而不用'!'。 – Birei

+2

哈希切片是perl中未评估的工具。 –

+0

切片应该只用于简单的事情。一些维护者迟早会用foreach循环替换上面的代码。编写代码,以便轻松维护。 “不要太聪明,”Damian Conway,Perl最佳实践http://oreilly.com/perl/excerpts/perl-best-practices/appendix-b.html – shawnhcorey