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 代码,而不是(双引号)字符串。只是为了进一步混淆事情,/ee
really 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:用不同大小的图案替换图案的主要内容,如果未能解决你的问题,请参考以下文章