在Perl中,如何使用`s ///`进行多次替换?

时间:2017-05-18 10:50:26

标签: regex perl

我的输入:

 $brackets = '\left \right \center \right \left \middle';

在上面的字符串中,我需要将每个\left字符串替换为(个大括号,将每个\right字符串替换为)个大括号。

我可以用几种方法替换以获得输出。但是我想知道如何在r修饰符中完成此操作。这是我到目前为止所拥有的

 $brackets=~s{\\(left|right)}{$&=~s/\\left/\(/r && $&=~s/\\right/\)/gr; }ge;

我不知道在哪里可以找到我的错误。

4 个答案:

答案 0 :(得分:6)

对于只涉及两个要替换的子字符串的文字问题,您应该使用两个单独的s///作为@Patrick85 recommends。只有当你有3个或更多这样的替代品时,下面的方法才有意义。在这种情况下,将映射隐藏在散列中将使您的代码更清晰。

使用哈希查找替换:

#!/usr/bin/env perl

use strict;
use warnings;

my %replacement = (
    '\left' => '(',
    '\right' => ')'
);

my $s = '\left \right \center \right \left \middle';
my $t = $s =~ s/( \\ (?: left | right ))/$replacement{$1}/rgx;

print "$s\n$t\n";

尝试将所有内容整合到一行中有很多问题:

$brackets=~s{\\(left|right)}{$&=~s/\\left/\(/r && $&=~s/\\right/\)/gr; }ge;

很难读懂。而且,不可能概括。如果您需要将 N 字符串映射到其替换项,会发生什么?让我们尝试通过添加一些空格来更清楚地写这个:

$brackets =~ s{
    \\
    (left | right)
}{
    $& =~ s/\\left/\(/r &&
    $& =~ s/\\right/\)/gr; 
}gex;

即使这样做了你想要的,你现在已经用一个简单的哈希查找替换了一个s///,并且对源字符串中的每个匹配执行了两次额外的s///操作。< / p>

对于您展示的示例字符串,此字符串将执行 其他s///操作。

这不好。

答案 1 :(得分:5)

使用两个简单的替换而不是一个复杂的替换:

#!/usr/bin/env perl
use strict;
use warnings;

my $brackets = '\left \right \center \right \left \middle';

$brackets =~ s/\\left/(/g;
$brackets =~ s/\\right/)/g;

print $brackets."\n";

输出:

( ) \center ) ( \middle

答案 2 :(得分:0)

建立一个替换列表相当容易。

use strict;
use warnings;

my $brackets = '\left \right \center \right \left \middle';

for ( $brackets ) {
    s/\\left/(/g;
    s/\\right/)/g;
}

print $brackets, "\n";

显然你仍然可以添加到列表中并删除空格。

More information about this method:

答案 3 :(得分:-4)

我需要关闭这个问题。答案由@Wiktor Stribiżew [评论]提供给我的答案。

$brackets = '\left \right \center \right \left \middle';

我的要求:

$brackets=~s{\\(left|right)}{$&=~s/\\left/\(/r && $&=~s/\\right/\)/gr; }ge;

答案:

$brackets=~s/\\((left)|right)/$2 ? '(' : ')'/eg;