Regex perl:用不同大小的模式替换模式

Regex perl:用不同大小的模式替换模式,regex,perl,substitution,Regex,Perl,Substitution,这是我的字符串A B C D,例如,我想用123替换A,用456替换C。然而,这不起作用 $string=~ s/A|B|C|D/123|B|456|D/; 我想要这个123 B 456 D但我得到这个123 | B | 456 | D B C D 可能是因为我的两个模式中的字符数不同 有没有一种方法可以用其他代码替换不同大小的模式?非常感谢。使用eval(未经测试)实现类似的功能 在s//表格中使用eval标志意味着评估替换 作为返回值的代码行的边 在这种情况下,它在替换代码中执行三元条件

这是我的字符串
A B C D
,例如,我想用
123
替换
A
,用
456
替换
C
。然而,这不起作用

$string=~ s/A|B|C|D/123|B|456|D/;
我想要这个
123 B 456 D
但我得到这个
123 | B | 456 | D B C D

可能是因为我的两个模式中的字符数不同


有没有一种方法可以用其他代码替换不同大小的模式?非常感谢。

使用eval(未经测试)实现类似的功能

s//
表格中使用eval标志意味着评估替换
作为返回值的代码行的边

在这种情况下,它在替换代码中执行三元条件

这有点像内联正则表达式回调。
但它要复杂得多,因为它可能类似于
s///eeg
so
最好参考文档


记住,eval真的很邪恶,拼写错误

你得到了我希望你得到的东西。您的正则表达式查找
'A'
'B'
'C'
'D'
的一个匹配项,并将其替换为文本字符串
'123 | B | 456 | D'
。因此
'abcd'
->
'123 | B | 456 | dbcd'

因此,它会找到第一个匹配项,即
'A'
,并用指定的字符串替换它。替换匹配各种字符串,但管道字符在替换槽中没有任何意义

您需要做的是创建从输入到输出的映射,如下所示:

my %map = ( A => '123', C => '456' );
然后你需要在替换中使用它。让我们为您提供一个搜索表达式:

my $search = join( '|', keys %map );
现在,让我们编写替换(当我编写包含代码的替换时,我更喜欢大括号:

$string =~ s{($search)}{ $map{$1} }g;
g
开关意味着我们可以匹配字符串的每个部分,
e
开关告诉Perl将替换表达式作为Perl代码进行计算


输出为“123 B 456 D”

最简单的方法是使用两个替换:

$string =~ s/A/123/g;
$string =~ s/B/456/g;
甚至(使用内联
for
循环作为对一个字符串应用多个替换的缩写):

当然,对于更复杂的模式,这可能不会产生与在一次过程中进行两次替换相同的结果;特别是,如果模式可以重叠(如A=
YZ
,B=
XY
),或者如果模式B可以匹配被替换为模式A的字符串,则可能会发生这种情况

如果希望一次性完成此操作,最通用的解决方案是使用,这会导致替换被解释为Perl代码,如中所示:

$string =~ s/(A|B)/ $1 eq 'A' ? '123' : '456' /eg;
您甚至可以在替换中包含多个表达式(用分号分隔);最后一个表达式的值将被替换到字符串中。如果您这样做,您可能会发现它对可读性很有用,如下所示:

$string =~ s{(A|B)}{
    my $foo = "";
    $foo = '123' if $1 eq 'A';
    $foo = '456' if $1 eq 'B';
    $foo;  # <-- this is what gets substituted for the pattern
}eg;
使用此方法,您甚至不需要
/e
修饰符(尽管在这个特定的示例中,添加修饰符不会产生任何影响)。使用
/e
的优点是,它可以实现比简单的哈希查找更复杂的选择替换规则。

String=“a B C D”


echo$String | perl-pi-e's/A/123/'&&perl-pi-e's/C/456/'

这应该可以。您的输出是什么?模式的相对大小和替换字符串无关紧要。您的示例代码对我来说非常好。您能显示完整的代码吗?它可以工作,谢谢!您能稍微解释一下公式吗?请注意,尽管有点误导人的缩写,
/e
实际上与
eval
无关。它只会导致替换的右侧被解析(在编译时)为Perl代码,而不是(双引号)为了进一步混淆问题,
/ee
对替换结果应用
eval
,并分享其“邪恶”(效率低下,缺乏编译时错误检查,如果应用于用户输入,安全漏洞的风险非常高)。当替换可以表示为简单的插值字符串时,不需要使用
/e
修饰符。
$string=~s/($search)/$map{$1}/g
就可以了
$string =~ s/(A|B)/ $1 eq 'A' ? '123' : '456' /eg;
$string =~ s{(A|B)}{
    my $foo = "";
    $foo = '123' if $1 eq 'A';
    $foo = '456' if $1 eq 'B';
    $foo;  # <-- this is what gets substituted for the pattern
}eg;
my %map = ('A' => '123', 'B' => '456');
$string =~ s/(A|B)/$map{$1}/g;