2012-03-05 58 views
5

我想使用一個「正則表達式編譯」的「類型」(我的意思是:一個表達式的形式qr/../)作爲用於散列結構的鍵。識別混雜鍵

要遍歷哈希凱斯時,常量字符串和正則表達式這些辨別之間,我試圖用ref(),或is_regexp(),但前者返回一個空字符串,而後者不能正常工作。恐怕我錯過了關於Perl refs和scalars的基本知識。

除此之外,我的解決辦法似乎工作。無論如何這太難看了嗎? 歡迎任何替代方案。

一些代碼來了解ref()功能:

my $regex = qr/foo/; 
printf "ref(\$regex): %s \n", ref($regex); 
printf "is_regexp(\$regex): %d \n", is_regexp($regex); 
# ref($regex): Regexp 
# is_regexp($regex): 1 

my $scalar = 3; 
printf "ref(\$scalar): [%s] \n", ref($scalar); 
# ref($scalar): [] 

my %my_hash = ('name', 'Becky', 'age', 23); 
for my $k (keys %my_hash) { 
    printf "%s [%s] -> %s [%s] \n", $k, ref($k), $my_hash{$k}, ref($my_hash{$k}); 
} 
# name [] -> Becky [] 
# age [] -> 23 [] 
+5

鍵在哈希是字符串。對於那些'ref'總是會返回'undef'。如果您使用任何不是字符串的鍵,它將轉換爲字符串。 – Qtax 2012-03-05 12:12:54

回答

7

由於Qtax在評論中指出,Perl的哈希鍵總是字符串:如果您使用的不是一個字符串作爲哈希鍵以外的東西,它是第一個轉換到一個字符串。

在另一個評論你寫:

「我從一個配置文件中讀取計數器定義;我希望能夠支持一些模式語法,例如:McDouglas,麥當勞,/ MC [A-ZA 。-z] * /我再從文本文件中讀取計數器的值,我相應地更新相關的計數器:麥當勞23麥金託什11"

如果我沒有理解這個權利,一個簡單的解決方案可能是存儲編譯的正則表達式在的另一個散列,鍵入他們的字符串表示形式:

my @patterns = (
    'McDouglas', 
    'McDonald', 
    'Mc[A-Za-z]*', 
); 

my %regexps = map +($_ => qr/^$_$/), @patterns; 
my %counters; 

while (<>) { 
    while (my ($pat, $re) = each %regexps) { 
     $counters{$pat}++ if /$re/; 
    } 
} 

foreach my $pat (@patterns) { 
    print "$pat: ", ($counters{$pat} || 0), "\n"; 
} 
2

這有什麼錯用Tie::RegexpHash?這樣可以節省你不必重新發明輪子:)

use Tie::RegexpHash; 

my %hash; 

tie %hash, 'Tie::RegexpHash'; 

$hash{ qr/^5(\s+|-)?gal(\.|lons?)?/i } = '5-GAL'; 

$hash{'5 gal'};  # returns "5-GAL" 
$hash{'5GAL'};  # returns "5-GAL" 
$hash{'5 gallon'}; # also returns "5-GAL" 
+0

雖然你建議的軟件包非常有趣,它執行的東西與我所需要的不同。在我的情況下,我不妨存儲定義正則表達式的純字符串(但我會失去正則表達式預編譯)。一種情況是trwo接近衝突的情況是需要存儲部分相互重疊的正則表達式。 – AndreaG 2012-03-05 12:44:11

+0

@AndreaG:請提供一個你的意思的例子。 – Zaid 2012-03-05 13:01:01

+0

我從配置文件讀取計數器定義;我希望能夠支持一些模式語法,例如:McDouglas,McDonald,/ Mc [A-Za-z] * /。我再從文本文件中讀取計數器的值,我相應地更新相關的計數器: 麥當勞23 麥金託什11 – AndreaG 2012-03-05 13:19:10