根据匹配的值替换regexp

根据匹配的值替换regexp,regex,perl,Regex,Perl,单个REGEXP是否可以根据匹配的值执行不同的替换 例如,给定字符串“aaa-bbb-ccc-aaa-ddd”,我想将每次出现的“aaa”替换为“alpha”,“bbb”替换为“beta”,“ccc”替换为“gamma”,而“ddd”替换为“delta” 使用四个单独的regexp替换非常容易,我知道: my $s = "aaa bbb ccc aaa ddd"; $s =~ s/aaa/alpha/g; $s =~ s/bbb/betaa/g; $s =~ s/ccc/gamma/g; $s

单个REGEXP是否可以根据匹配的值执行不同的替换

例如,给定字符串“aaa-bbb-ccc-aaa-ddd”,我想将每次出现的“aaa”替换为“alpha”,“bbb”替换为“beta”,“ccc”替换为“gamma”,而“ddd”替换为“delta”

使用四个单独的regexp替换非常容易,我知道:

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


这只是我试图解决的更复杂问题的一个简化示例;请不要开始争论我问错了问题,我应该用不同的方式来做。。。如果您真的这么认为,请忽略这个问题。

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

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;

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

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;

一个可以使用的东西是,这意味着右侧被解释为代码,匹配的文本被替换为该代码返回的值

例如,您可能需要以下内容:

$s =~ s/aaa|bbb|ccc/ $& eq 'aaa' ? 'alpha' : $& 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
    解决方案在时间上是线性的,在空间上是恒定的,而散列解决方案(大致)在时间上是恒定的,在空间上是线性的

  • 在本地,
    /e
    的速度提高了5–10%,而
    %的替换使用了588字节的内存。基准代码为:

    my$str=‘aaa bbb ccc aaa ddd’; 我的$pattern=qr{(aaa | bbb | ccc | ddd)}x; 我的更换率=(“aaa”=>“α”、“bbb”=>“β”、“ccc”=>“γ”、“ddd”=>“δ”); CMP这些(10000000, { e=>sub{my$s=$str;$s=~s/$pattern/$1eq'aaa'?'alpha':$1eq'bbb'?'beta':$1eq'c'?'gamma':'delta'/eg}, h=>sub{my$s=$str;$s=~s/$pattern/$replacement{$1}/ge;}, } );


  • 一个可以使用的东西是,这意味着右侧被解释为代码,匹配的文本被替换为该代码返回的值

    例如,您可能需要以下内容:

    $s =~ s/aaa|bbb|ccc/ $& eq 'aaa' ? 'alpha' : $& 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
      解决方案在时间上是线性的,在空间上是恒定的,而散列解决方案(大致)在时间上是恒定的,在空间上是线性的

  • 在本地,
    /e
    的速度提高了5–10%,而
    %的替换使用了588字节的内存。基准代码为:

    my$str=‘aaa bbb ccc aaa ddd’; 我的$pattern=qr{(aaa | bbb | ccc | ddd)}x; 我的更换率=(“aaa”=>“α”、“bbb”=>“β”、“ccc”=>“γ”、“ddd”=>“δ”); CMP这些(10000000, { e=>sub{my$s=$str;$s=~s/$pattern/$1eq'aaa'?'alpha':$1eq'bbb'?'beta':$1eq'c'?'gamma':'delta'/eg}, h=>sub{my$s=$str;$s=~s/$pattern/$replacement{$1}/ge;}, } );


  • 我不这么认为。但我可能错了,我不这么认为。但我可能错了,我不知道你的意思。在您的语句中,$pattern和$replacement是什么?您应该使用
    my$pattern=join'|',映射quotemeta,对{length$b length$a}键进行排序%changes
    以确保在
    aa
    之前找到匹配项,例如,
    aabbcc
    。我不知道您的意思。在您的语句中,$pattern和$replacement是什么?您应该使用
    my$pattern=join'|',映射quotemeta,排序{length$b length$a}键%changes
    来确保匹配,例如,
    aabbcc
    位于
    aa
    之前。从任何角度看,哈希都比长字符串条件运算符好得多。从任何角度看,哈希都比长字符串条件运算符好得多。