perl:用不同大小的图案替换图案

Posted

技术标签:

【中文标题】perl:用不同大小的图案替换图案【英文标题】:perl: substitute pattern with pattern of different size 【发布时间】:2015-06-12 21:40:58 【问题描述】:

这是我的字符串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

可能是因为我的两种模式的字符数不同。

有没有办法使用其他代码替换不同大小的模式?非常感谢。

【问题讨论】:

这应该可以。你的输出是什么? 模式和替换字符串的相对大小无关紧要。您的示例代码非常适合我。你能显示完整的代码吗? 【参考方案1】:

你得到了我希望你得到的。您的正则表达式查找 一个 出现 'A''B''C''D' 并将其替换为 文字字符串 @987654325 @。因此'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$1 g;

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

输出为'123 B 456 D'

【讨论】:

当替换可以表示为简单的插值字符串时,不需要/e 修饰符。 $string =~ s/($search)/$map$1/g 很好【参考方案2】:

使用 eval 的类似方法(未经测试)。

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

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

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

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

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

【讨论】:

它有效,谢谢!你能解释一下这个公式吗? 请注意,尽管有一些误导性的缩写,/e 确实与eval 无关。它只是导致将替换的右侧(在编译时)解析为 Perl 代码,而不是(双引号)字符串。只是为了进一步混淆事情,/eereally does 将eval 应用于替换的结果,并且确实分享了它的“邪恶”(效率低下,缺乏编译时错误检查,如果应用于用户输入)。【参考方案3】:

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

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

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

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

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

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

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

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

$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;

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

【讨论】:

【参考方案4】:

String="A B C D"

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

【讨论】:

以上是关于perl:用不同大小的图案替换图案的主要内容,如果未能解决你的问题,请参考以下文章

在修复画笔工具的工具选择栏中有很多选项,下列说法错误的是()。

多媒体技术2023-04-08

怎样用C语言输出一个彩色的图案(不利用图片文件)?

用unity3d 在正方体6面 画不同的图案,怎么实现

KineticJS - 图像上的图案和填充

用unity3d 在正方体6面 画不同的图案,怎么实现