[英]Perl: Greedy nature refuses to work
I am trying to replace a string with another string, but the greedy nature doesn't seem to be working for me. 我试图用另一个字符串替换一个字符串,但贪婪的性质似乎并不适合我。 Below is my code where "PERFORM GET-APLCY" is identified and replaced properly, but string "PERFORM GET-APLCY-SOI-CVG-WVR" and many other such strings are being replaced by the the replacement string for "PERFORM GET-APLCY".
下面是我的代码,其中“PERFORM GET-APLCY”被识别并正确替换,但字符串“PERFORM GET-APLCY-SOI-CVG-WVR”以及许多其他此类字符串正被“PERFORM GET-APLCY”的替换字符串替换”。
s/PERFORM $func[$i]\.*/# PERFORM $func[$i]\.\n $hash{$func[$i]}/g;
where the full stop is optional during string match and replacement. 在字符串匹配和替换期间,句号是可选的。 I have also tried giving the pattern to be matched as $func[$i]\\b Please help me understand what the issue could be.
我也试过让模式匹配为$ func [$ i] \\ b请帮助我理解问题所在。
Thanks in advance, Faez 在此先感谢,Faez
Why GET-APLCY-
should not match GET-APLCY.
为什么
GET-APLCY-
不应该与GET-APLCY.
匹配GET-APLCY.
, if the dot is optional? ,如果点是可选的?
Easy solution: sort your array by length in descending order. 简单的解决方案:按长度按降序排列数组。
@func = sort { length $b <=> length $a } @func
Testing script: 测试脚本:
#!/usr/bin/perl
use warnings;
use strict;
use feature 'say';
my %hash = ('GET-APLCY' => 'REP1',
'GET-APLCY-SOI-CVG-WVR' => 'REP2',
'GET-APLCY-SOI-MNG-CVRW' => 'REP3',
);
my @func = sort { length $b <=> length $a } keys %hash;
while (<DATA>) {
chomp;
print;
print "\t -> \t";
for my $i (0 .. $#func) {
s/$func[$i]/$hash{$func[$i]}/;
}
say;
}
__DATA__
GET-APLCY param
GET-APLCY- param
GET-APLCY. param
GET-APLCY-SOI. param
GET-APLCY-SOI-CVG-WVR param
GET-APLCY-SOI-MNG-CVRW param
You appear to be looping over function names, and calling s///
for each one. 您似乎在循环函数名称,并为每个名称调用
s///
。 An alternative is to use the e
option, and do them all in one go (without a loop): 另一种方法是使用
e
选项,一次完成它们(没有循环):
my %hash = (
'GET-APLCY' => 'replacement 1',
'GET-APLCY-SOI-CVG-WVR' => 'replacement 2',
);
s{
PERFORM \s+ # 'PERFORM' keyword
([A-Z-]+) # the original function name
\.? # an optional period
}{
"# PERFORM $1.\n" . $hash{$1};
}xmsge;
The e
causes the replacement part to be evaluated as an expression. e
使得替换部件被评估为表达式。 Basically, the first part finds all PERFORM
calls (I'm assuming that the function names are all upper case with '-' between them – adjust otherwise). 基本上,第一部分找到所有
PERFORM
调用(我假设函数名都是大写的,在它们之间加' - ' - 否则调整)。 The second part replaces that line with the text you want to appear. 第二部分将该行替换为您要显示的文本。
I've also used the x
, m
, and s
options, which is what allows the comments in the regular expression, among other things. 我还使用了
x
, m
和s
选项,这些选项允许正则表达式中的注释等。 You can find more about these under perldoc perlop
. 您可以在
perldoc perlop
下找到更多相关信息。
A plain version of the s
-line should be: s
line的简单版本应该是:
s/PERFORM ([A-Z-]+)\.?/"# PERFORM $1.\n" . $hash{$1}/eg;
I guess that $func[$i] contains "GET-APLCY". 我猜$ func [$ i]包含“GET-APLCY”。 If so, this is because the star only applies to the dot, an actual dot, not "any character".
如果是这样,这是因为星号仅适用于点,实际点,而不是“任何字符”。 Try
尝试
s/PERFORM $func[$i].*/# PERFORM $func[$i]\.\n $hash{$func[$i]}/g;
I'm pretty sure you trying to do some kind of loop for $i. 我很确定你试图为$ i做一些循环。 And in that case most likely GET-APLCY is located in @func array before GET-APLCY-SOI-CVG-WVR.
在那种情况下,最有可能的GET-APLCY位于GET-APLCY-SOI-CVG-WVR之前的@func阵列中。 So I recommend to reverse sort @func before entering loop.
所以我建议在进入循环之前反向排序@func。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.