Regex 在LHS中分组的Perl正则表达式

Regex 在LHS中分组的Perl正则表达式,regex,perl,Regex,Perl,如何匹配下一行 sometext_TEXT1.yyy-TEXT1.yyy anothertext_OTHER.yyy-MAX.yyy 要删除结尾处的-repetative.text,但仅当它重复时 sometext_TEXT1.yyy anothertext_OTHER.yyy-MAX.yyy 我的努力 use strictures; my $text="sometext_TEXT1.xxx-TEXT1.xxx"; $text =~ s/(.*?)(.*)(\s*-\s*$2)/$1$2/;

如何匹配下一行

sometext_TEXT1.yyy-TEXT1.yyy
anothertext_OTHER.yyy-MAX.yyy
要删除结尾处的
-repetative.text
,但仅当它重复时

sometext_TEXT1.yyy
anothertext_OTHER.yyy-MAX.yyy
我的努力

use strictures;
my $text="sometext_TEXT1.xxx-TEXT1.xxx";
$text =~ s/(.*?)(.*)(\s*-\s*$2)/$1$2/;
print "$text\n";
印刷品

Use of uninitialized value $2 in regexp compilation at a line 3.
换句话说,为下一个
split+match
寻找更好的解决方案

while(<DATA>) {
        chomp;

        my($first, $second) = split /\s*-\s*/;
        s/\s*-\s*$second$// if ( $first =~ /$second$/ );

        print "$_\n";
}
__DATA__
sometext_TEXT1.yyy-TEXT1.yyy
anothertext_OTHER.yyy-MAX.yyy
while(){
咀嚼;
我的($first,$second)=拆分/\s*-\s*/;
s/\s*-\s*$second$//如果($first=~/$second$/);
打印“$\u\n”;
}
__资料__
sometext\u TEXT1.yyy-TEXT1.yyy
另一个文本_OTHER.yyy-MAX.yyy

当您使用
$2
时,Perl将尝试插入该变量,但该变量将仅在匹配完成后设置。您需要的是一个反向引用,您需要使用
\2

$text =~ s/(.*?)(.*)(\s*-\s*\2)/$1$2/;
请注意,在评估更换零件时,已设置了
$1
$2
,并且可以按预期进行插值。此外,您还可以使用以下方法使模式更简洁(并且可能更高效):

$text =~ s/(.*)\s*-\s*\2/$1/;
如果初始部分(
*?
)是任意的,并且您只需将其写回,则无需匹配它。不过,您可能要做的是将模式锚定到字符串的末尾:

$text =~ s/(.*)\s*-\s*\1$/$1/;
否则(在你或我最初的尝试中),你会将
somethingelse
变成
somethingelse

$text =~ s/(.*?)(.*)(\s*-\s*$2)/$1$2/;
这个正则表达式有各种问题,但走的是正确的道路

  • 使用
    \2
    (或更好的方法:
    \g2
    \g{-1}
    )或其他方法来引用捕获组的内容。执行Perl语句时,
    $2
    变量被插入。当时,
    $2
    未定义,因为之前没有匹配项。您将收到一条警告,因为它未初始化。即使定义了它,模式也会在编译期间被修复

  • 您定义了三个捕获组,但只需要一个。
    \K
    eep指令有一个技巧:它让正则表达式引擎忘记先前匹配的文本,这样它就不会受到替换的影响。也就是说,
    s/(foo)b/$1/
    相当于
    s/foo\Kb/
    。其效果类似于可变长度查找

  • (.*)(.*)
    部分有点像是一场恶梦。我们可以通过增加更多的条件来降低比赛成本,例如,在比赛开始和结束时固定模式。使用以上修改,我们现在有了
    s/^.*(.*)\K\s*-\s*\g1$/
    。但是仔细想想,我们可以删除
    ^.*?
    ,因为这描述了regex引擎所做的事情

  • 一个简短的测试:

    while(<DATA>) {
      s/(.*)\K\s*-\s*\g1$//;
      print;
    }
    __DATA__
    sometext_TEXT1.yyy-TEXT1.yyy
    anothertext_OTHER.yyy-MAX.yyy
    

    关于您的
    split
    ting解决方案的几句话:这也会缩短行数

    sometext_TEXT1xyyy - 1.xyyy
    
    因为当你把一个变量插入一个正则表达式时,它的内容并不完全匹配。相反,它们被解释为一种模式(其中
    匹配任何非换行代码点)!可以通过使用
    \Q..\E
    转义引用所有元字符来避免这种情况:

    s/\s*-\s*\Q$second\E$// if $first =~ /\Q$second\E$/;
    

    替换的匹配部分中的反向引用必须是\2而不是$2最后一个正则表达式应该是
    $text=~s/(.*)\s*-\s*\1$/$1/…:)
    
    s/\s*-\s*\Q$second\E$// if $first =~ /\Q$second\E$/;