2013-07-11 14 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,而不是字面替换