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

perl: substitute pattern with pattern of different size

这是我的字符串 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(未经测试)。

$string=~ s/(A)|C/ length() ? '123': '456'/eg;  

s///形式中使用eval标志意味着计算替换
边作为一行代码表示returns一个值。

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

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

记住,eval真的很邪恶,拼错了!!

你得到了我希望你得到的。您的正则表达式查找 one 出现的 'A''B''C''D' 并将其替换为文字字符串 '123|B|456|D'。因此 'A B C D' -> '123|B|456|D B C D'

因此它会找到第一个出现的地方,即 'A' 并将其替换为您指定的字符串。 alternation 匹配各种字符串,但管道字符在替换槽中没有任何意义。

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

my %map = ( A => '123', C => '456' );

然后你需要在替换中使用它。让我们给你一个搜索表达式:

my $search = join( '|', keys %map );

现在让我们编写替换(当我编写其中包含代码的替换时,我更喜欢大括号:

$string =~ s{($search)}{ $map{} }g;

g 开关意味着我们可以匹配字符串的每一部分,而 e 开关告诉 Perl 评估 替换表达式作为 Perl代码。

输出为'123 B 456 D'

最简单的方法是进行两次替换:

$string =~ s/A/123/g;
$string =~ s/B/456/g;

甚至(使用内联 for 循环作为 shorthand 对一个字符串应用多个替换):

s/A/123/g, s/B/456/g for $string;

当然,对于更复杂的模式,这可能不会产生与一次完成两个替换相同的结果;特别是,如果模式可以重叠(如 A = YZ、B = XY),或者如果模式 B 可以匹配替换模式 A.

的字符串,则可能会发生这种情况

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

$string =~ s/(A|B)/  eq 'A' ? '123' : '456' /eg;

您甚至可以在替换中包含多个表达式,用分号分隔;最后一个表达式的值将被替换到字符串中。如果这样做,您可能会发现使用 paired delimiters 提高可读性很有用,例如:

$string =~ s{(A|B)}{
    my $foo = "";
    $foo = '123' if  eq 'A';
    $foo = '456' if  eq 'B';
    $foo;  # <-- this is what gets substituted for the pattern
}eg;

如果您的模式是常量字符串(如上面的简单示例),则更有效的解决方案是使用查找哈希,如:

my %map = ('A' => '123', 'B' => '456');
$string =~ s/(A|B)/$map{}/g;

使用此方法,您甚至不需要 /e 修饰符(尽管对于这个特定示例,添加它没有任何区别)。使用 /e 的优点是它允许您实施比简单的哈希查找所允许的更复杂的规则来选择替换。

String="A B C D"

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