【问题标题】:regexp replacement depending on matched value正则表达式替换取决于匹配值
【发布时间】:2014-04-27 11:12:57
【问题描述】:

是否可以使用单个正则表达式根据匹配的值执行不同的替换?

例如,给定字符串“aaa bbb ccc aaa ddd”,我想用“alpha”替换每次出现的“aaa”,用“beta”替换“bbb”,用“gamma”和“ddd”替换“ccc” " 与 "delta"。

我知道,用四个单独的正则表达式替换很容易做到:

my $s = "aaa bbb ccc aaa ddd";
$s =~ s/aaa/alpha/g;
$s =~ s/bbb/betaa/g;
$s =~ s/ccc/gamma/g;
$s =~ s/ddd/delta/g;

问题是是否可以只用一个语句来做同样的事情:

$s =~ s/$pattern/$replacement/g;

如果这很重要,我正在使用 perl。

这只是我试图解决的更复杂问题的简化示例;请不要开始争辩说我问错了问题,我应该以不同的方式做...如果你真的相信,请忽略这个问题。

【问题讨论】:

  • 我不这么认为。但我可能错了。

标签: regex perl


【解决方案1】:

您可以使用哈希将匹配项替换为所需的值,

my %replacement = (
    "aaa" => "alpha",
    "bbb" => "beta", 
    "ccc" => "gamma",
    "ddd" => "delta",
);
my ($pattern) = map qr/$_/, join "|", map quotemeta, keys %replacement;

$s =~ s/($pattern)/$replacement{$1}/ge;

【讨论】:

  • 不确定我理解你的意思。您的语句中的 $pattern 和 $replacement 会是什么?
  • 您应该使用my $pattern = join '|', map quotemeta, sort { length $b <=> length $a } keys %changes 来确保在aa 之前找到与aabbcc 的匹配项。
【解决方案2】:

可以提供的一件事是/e modifier to s///,,这意味着右侧被解释为代码,匹配的文本被此代码返回的值替换。

对于你的例子,你会想要这样的东西:

$s =~ s/aaa|bbb|ccc/ $& eq 'aaa' ? 'alpha' : $& eq 'bbb' ? 'beta' : 'gamma' /eg;

或更好(因为使用 $& 会降低性能):

$s =~ s/(aaa|bbb|ccc)/ $1 eq 'aaa' ? 'alpha' : $1 eq 'bbb' ? 'beta' : 'gamma' /eg;

顺便说一句,如果您的表达式变得非常大,您可能还想使用不同的分隔符和/x 修饰符来提高可读性。示例:

$s =~ s
        { ( aaa | bbb | ccc ) }
        {
            $1 eq 'aaa'
                ? 'alpha'
                : $1 eq 'bbb'
                    ? 'beta'
                    : 'gamma'
        }egx;

编辑:质量

我提出这个答案是因为问题要求根据匹配值进行替换,但没有具体说明在他们的实际问题中(与他们展示的简化版本相反),对匹配值的测试是否为一个简单的相等测试。

有人提出,基于/e 的解决方案的质量低于基于散列的解决方案。这个观察在一定程度上是有效的。在我看来,解决方案不同的两个质量因素是:

  • 易读性:在这一点上,哈希解决方案无疑是赢家。
  • 资源使用:在 OP 提出的示例中,/e 解决方案在时间和空间使用方面均胜出¹。如果问题变得更大,两种解决方案的规模会有所不同:/e 解决方案在时间上是线性的,在空间上是恒定的,而哈希解决方案在时间上是(大致)恒定的,在空间上是线性的。

  1. 在本地,/e 快 5–10%,%replacement 使用 588 字节的内存。基准代码是:

    我的 $str = 'aaa bbb ccc aaa ddd'; 我的 $pattern = qr{ (aaa | bbb | ccc | ddd ) }x; 我的 %replacement = ( "aaa" => "alpha", "bbb" => "beta", "ccc" => "gamma", "ddd" => "delta", ); cmpthese( 10000000, { e => sub { 我的 $s = $str; $s =~ s/$pattern/$1 eq 'aaa' ? 'alpha' : $1 eq 'bbb' ? “测试版”:1 美元当量“c”? '伽玛':'delta'/例如}, h => sub { 我的 $s = $str; $s =~ s/$pattern/$replacement{$1}/ge; }, } );

【讨论】:

  • 哈希是一种的机制,几乎可以用任何方法来衡量,而不是一长串条件运算符。
猜你喜欢
  • 2012-05-16
  • 2013-12-06
  • 2021-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-19
  • 1970-01-01
  • 2019-03-14
相关资源
最近更新 更多