如何更换一组搜索/替换对?

时间:2013-07-11 15:02:09

标签: perl

我有一个翻译字典作为哈希:

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

(实际用例不是人类语言翻译!我正在用一些其他值替换一堆令牌。这仅仅是例如。)

如何将每个应用于字符串?显然我可以循环它们并将每个传递给s/$key/$value/,但是我必须引用它们,这样如果搜索或替换中有(例如)/,它就不会中断。

在PHP中有strtr($subject, $replacement_pairs_array) - Perl中有类似内容吗?

3 个答案:

答案 0 :(得分: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函数转义正则表达式元字符可以避免这种情况。

传统的方法是构建一个匹配所有键的正则表达式:

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

然后:

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

解决了所有这些问题。

在正则表达式构建代码中,我们首先使用map quotemeta转义所有键,然后使用|连接字符串以构建匹配所有键的正则表达式。由此产生的正则表达式非常有效。

这可以保证字符串的每个部分只翻译一次。

答案 1 :(得分: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而不是文字替换

答案 2 :(得分:1)

似乎有一个CPAN module会执行此操作