简体   繁体   English

Perl:贪婪的自然拒绝工作

[英]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. 我还使用了xms选项,这些选项允许正则表达式中的注释等。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM