Perl:贪婪的本性拒绝工作



我正试图用另一个字符串替换一个字符串,但贪婪的本质似乎对我不起作用。下面是我的代码,其中"PERFORM GET-APLCY"被正确识别和替换,但字符串"PERFORMGET-APCCY-SOI-VG-WVR"和许多其他这样的字符串正在被"PERFORMGet-APLCY"的替换字符串替换。

s/PERFORM $func[$i].*/#  PERFORM $func[$i].n $hash{$func[$i]}/g;

其中,在字符串匹配和替换期间,句号是可选的。我还尝试将要匹配的模式设置为$func[$I]\b请帮助我了解问题可能是什么。

提前感谢,Faez

如果点是可选的,为什么GET-APLCY-不应该与GET-APLCY.匹配?

简单的解决方案:按长度降序对数组进行排序。

@func = sort { length $b <=> length $a } @func

测试脚本:

#!/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

您似乎在函数名上循环,并为每个函数名调用s///。另一种选择是使用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;

e使得替换部分被评估为表达式。基本上,第一部分查找所有PERFORM调用(我假设函数名都是大写,中间有'-',否则进行调整)。第二部分用要显示的文本替换该行。

我还使用了xms选项,这些选项允许在正则表达式中添加注释。你可以在perldoc perlop下找到更多关于这些的信息。

s行的普通版本应该是:

s/PERFORM ([A-Z-]+).?/"#  PERFORM $1.n" . $hash{$1}/eg;

我猜$func[$I]包含"GET-APLCY"。如果是这样,这是因为星形只适用于点,一个实际的点,而不是"任何字符"。尝试

s/PERFORM $func[$i].*/#  PERFORM $func[$i].n $hash{$func[$i]}/g;

我敢肯定你正在为$I做某种循环。在这种情况下,很可能GET-APPLY位于GET-APPLY-SOI-CVG-WVR之前的@func阵列中。所以我建议在进入循环之前对@func进行反向排序。

最新更新