2013-07-11 18 views
2

我有翻譯爲散列的字典:!如何替換一組搜索/替換對?

my %dict = { hello => 'hola', goodbye => 'adios' , ... } 

(實際使用情況是不是人類語言翻譯,我更換了一些其他值令牌的負載這只是舉例)

如何將這些應用到字符串中?很明顯,我可以循環他們,並將每個傳遞給s/$key/$value/,但之後我必須引用它們,以便在搜索或替換(例如)/時不會中斷。

在PHP中有strtr($subject, $replacement_pairs_array) - Perl中是否有類似的東西?

+0

當''key'爲'/'且'$ value'爲'%'時,perl不會像php那樣愚蠢's/$ key/$ value /'''''''''' – user1937198

+0

' s/$ _/$ dict {$ _} /鍵%dict;'是最簡單的方法。 – user1937198

+1

@ user1937198是的,但是如果$ key是'(',那麼perl會非常不高興,請參閱下面的amon的回答:PHP的strtr不是基於正則表達式的東西,所以它不需要這個引用。 – artfulrobot

回答

6

首先,您的哈希初始化已關閉:哈希初始化爲清單:

my %dict = (hello => 'hola', goodbye => 'adios' , ...); 

或者你可以使用一個散列引用:

my $dict = { hello => 'hola', goodbye => 'adios' , ... }; 

這是一個標量。

更換與在串中的值的鍵很容易:

s/$_/$dict{$_}/g for keys %dict; 

除非

  • 置換的內容不應被取代,例如%dict = (a => b, b => c)應該將"ab"轉換爲"bc"(而不是"cc",因爲上述解決方案可能做或可能不做,哈希順序是隨機的)。
  • 這些鍵可以包含正則表達式元字符,如.,+()。這可以通過使用quotemeta函數轉義正則表達式元字符來避開。

傳統的做法是建立所有的鍵相匹配的正則表達式:解決了所有這些問題

$string =~ s/($keys_regex)/$dict{$1}/g; 

my $keys_regex = join '|', map quotemeta, keys %dict; 

然後。

在正則表達式構建代碼中,我們首先使用map quotemeta轉義所有的鍵,然後使用|連接字符串來構建匹配所有鍵的正則表達式。得到的正則表達式非常有效。

這保證字符串的每個部分只翻譯一次。

+0

哇!(謝謝你提供了這樣一個信息豐富的答案!)(是的,對不起'哈特的事情,obv這不是真正的代碼..) – artfulrobot

+0

我通常將鍵正則表達式轉換成正則表達式$ keys_regex = qr /($ keys_regex)/'即使's/$ keys_regex/$ dict {$ 1}/g;'被多次使用,正則表達式也只能被編譯一次,順便提一句,它具有有趣的性能特點,'$ keys_regex'將被轉換成Aho-Corasick並且進行線性搜索時間,它像地獄一樣快。 –

2
%dict = ('hello' => 'hola', 'goodbye' => 'adios'); 
my $x="hello bob, goodbye sue"; 
my $r=join("|",keys %dict); 
$x=~s/($r)/$dict{$1}/ge; 
print $x; 

這說明這樣做的一種方式。

將散列鍵轉換爲交替的正則表達式,即「hello | goodbye」,查找與該表達式的匹配,然後使用找到的鍵來查找散列中的值。使用g標誌將regexp全局或重複應用於字符串,並使用e標誌將替換表達式評估爲perl,而不是字面替換