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$/;