用正则表达式交换字母

时间:2014-04-17 12:20:50

标签: regex perl replace

如何将字母oeeo交换?

我刚试过这个,但我不认为这是一个很好的方法。还有更好的方法吗?

my $str  = 'Absolute force';
$str =~ s/e/___eee___/g;
$str =~ s/o/e/g;
$str =~ s/___eee___/o/g;

输出:Abseluto ferco

4 个答案:

答案 0 :(得分:25)

使用transliteration operator

$str =~ y/oe/eo/;

E.g。

$ echo "Absolute force" | perl -pe 'y/oe/eo/'
Abseluto ferco

答案 1 :(得分:8)

正如已经说过的,这样做的方法是transliteration operator

  

tr/SEARCHLIST/REPLACEMENTLIST/cdsr

     

y/SEARCHLIST/REPLACEMENTLIST/cdsr

     

使用替换列表中的相应字符音译搜索列表中找到的所有出现的字符。它返回替换或删除的字符数。如果未通过=~!~运算符指定字符串,则$_字符串将被音译。

但是,我想赞扬您对正则表达式的创造性使用。您的解决方案有效,但占位符字符串_ee_已足够。

tr只会帮助你进行角色替换,所以我想快速教你如何利用正则表达式进行更复杂的质量替换。基本上,您只需使用/e标记在RHS中执行代码。以下内容也将用于您的目标:

my $str  = 'Absolute force';

$str =~ s/([eo])/$1 eq 'e' ? 'o' : 'e'/eg;

print $str;

输出:

Abseluto ferco

注意LHS(左侧)如何匹配oe,并且RHS(右侧)进行测试以查看哪个匹配并返回相反的替换。< / p>

现在,通常会有一个要替换的单词列表,因此可以方便地构建from / to值的哈希值,然后动态构建正则表达式。以下是:

my $str  = 'Hello, foo. How about baz? Never forget bar.';

my %words = (
    foo  => 'bar',
    bar  => 'baz',
    baz  => 'foo',
);
my $wordlist_re = '(?:' . join('|', map quotemeta, keys %words) . ')';

$str =~ s/\b($wordlist_re)\b/$words{$1}/eg;

输出:

Hello, bar. How about foo? Never forget baz.

上述内容可能适用于您的eo案例,但这样做会有些过分。请注意我如何使用quotemeta来转义键,以防它们包含正则表达式特殊字符。我还故意在$wordlist_re中使用了一个非捕获组,以便变量可以放入任何正则表达式并按照需要运行。然后我将捕获组放在s///内,因为能够看到正则表达式中捕获的内容非常重要,而不必回溯到插值变量的值。

答案 2 :(得分:2)

来自man sed

  

<强> Y /源/目标/                  将源中出现的模式空间中的字符音译为dest中的相应字符。

tr命令也可以这样做:

$ echo "Absolute force" | tr 'oe' 'eo'
Abseluto ferco

答案 3 :(得分:2)

tr///运营商是最好的。但是,如果您想使用s///运算符(处理多个单字母替换),您可以编写

$ echo 'Absolute force' | perl -pe 's/(e)|o/$1 ? "o" : "e"/eg'
Abseluto ferco

捕获括号可以避免在@ Miller的答案中进行多余的$1 eq 'e'测试。