2013-07-07 26 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