Regex Perl正则表达式如何在下一个匹配中重复使用上一个匹配的一部分?

Regex Perl正则表达式如何在下一个匹配中重复使用上一个匹配的一部分?,regex,perl,Regex,Perl,我需要一些Perl正则表达式帮助。下面是一段代码: use strict; use warnings; my $str = "In this example, A plus B equals C, D plus E plus F equals G and H plus I plus J plus K equals L"; my $word = "plus"; my @results = (); 1 while $str =~ s/(.{2}\b$word\b.{2})/push(@res

我需要一些Perl正则表达式帮助。下面是一段代码:

use strict; 
use warnings; 
my $str = "In this example, A plus B equals C, D plus E plus F equals G and H plus I plus J plus K equals L"; 
my $word = "plus"; 
my @results = ();
1 while $str =~ s/(.{2}\b$word\b.{2})/push(@results,"$1\n")/e;
print @results;
生成以下输出:

A plus B D plus E 2 plus F H plus I 4 plus J 5 plus K A加B D+E 2加F H+I 4加J 5加K 我想看到的是,一个已经匹配的角色可以出现在不同上下文中的新匹配中:

A plus B D plus E E plus F H plus I I plus J J plus K A加B D+E E加F H+I 我加J J+K
如何更改正则表达式以获得此结果?谢谢---Dan这里有一个方法:

use strict; 
use warnings; 
my $str = "In this example, A plus B equals C, D plus E plus F equals G and H plus I plus J plus K equals L"; 
my $word = "plus"; 
my @results = ();
my $i = 0;
while (substr($str, $i) =~ /(.{2}\b$word\b.{2})/) {
    push @results, "$1\n";
    $i += $-[0] + 1;
}
print @results;

它不是非常像Perl,但它可以工作,并且没有使用太多晦涩的正则表达式技巧。但是,您可能必须在中查找特殊变量
@-
的函数。

一般建议:如果需要
m/
,请不要使用
s//
。在匹配的内容上要具体

答案是:

输出:

C:\Temp> b 'A plus B' 'D plus E' 'E plus F' 'H plus I' 'I plus J' 'J plus K' C:\Temp>b “A加B” “D加E” “E加F” “H加上我” “我加J” “J+K”
您可以使用
m//g
而不是
s//
,并将其分配给
pos
功能,以便在第二个术语之前回放匹配位置:

use strict;
use warnings;

my $str  = 'In this example, A plus B equals C, D plus E plus F equals G and H plus I plus J plus K equals L';
my $word = 'plus';
my @results;

while ($str =~ /(.{2}\b$word\b(.{2}))/g) {
    push @results, "$1\n";
    pos $str -= length $2;
}
print @results;

不必使用正则表达式。基本上,只需拆分字符串,使用循环遍历每个项目,检查“加号”,然后从前后获取单词

my $str = "In this example, A plus B equals C, D plus E plus F equals G and H plus I plus J plus K equals L"; 
@s = split /\s+/,$str;
for($i=0;$i<=scalar @s;$i++){
    if ( "$s[$i]"  eq "plus" ){
        print "$s[$i-1] plus $s[$i+1]\n";
    }
}
my$str=“在本例中,A+B等于C,D+E+F等于G,H+I+J+K等于L”;
@s=split/\s+/,$str;
对于($i=0;$i给出“完全公开”的评论(但假设
{0,35}
,而不是
{35}
),我会这样做


如果你真的是想
(?s:.{0,35})

的话,你可以跳过替换。另一个选择是使用前瞻:

use strict; 
use warnings; 
my $str = "In this example, A plus B equals C, D plus E "
        . "plus F equals G and H plus I plus J plus K equals L"; 
my $word = "plus"; 
my $chars = 2;
my @results = ();

push @results, $1 
  while $str =~ /(?=((.{0,$chars}?\b$word\b).{0,$chars}))\2/g;

print "'$_'\n" for @results;

在前瞻中,捕获组1与单词以及可变数量的前导和尾随上下文字符相匹配,最大值为您设置的最大值。当前瞻完成时,反向引用
\2
匹配“for real”第2组捕获的内容与第1组相同,只是它停在单词的末尾。这将
pos
设置在您想要的位置,而不需要您计算单词后面实际匹配的字符数。

啊,基本上是相同的答案,但您也清理了正则表达式。
pos
感觉很干净er than
substr
。感谢Greg、Sinan和Michael的快速响应。完整披露:引用的示例是一个简化,$str实际上是产品用户手册中的500k个字符,$word是可能的单词命中列表中的一个元素,{2}实际上是{35},并且可以捕获“plus”周围的任何字符在本文中,为了建立文档中如何使用“plus”的完整一致性,因此获得了最快性能的分数--DanThanks发布,我了解了更多关于regex的信息。我想知道,这个解决方案或使用pos()的Sinan的解决方案哪个更快?它们并不完全相同。基于您最初的问题,Sinan的代码在两端正好匹配2个额外字符,并将
pos
恰好向后突出一个位置。我的代码允许可变数量的上下文字符(在本例中,2是最大值),这在阅读您的“完全披露”后看起来更为现实注释。我的解决方案可以更有效地与ysth进行比较,我希望他的更快,因为它可以让正则表达式引擎找到
\b$word\b
的匹配项,而无需添加不情愿的量词。
use List::Util qw/max min/;
my $context = 35;
while ( $str =~ /\b$word\b/g ) {
    my $pre = substr( $str, max(0, $-[0] - $context), min( $-[0], $context ) );
    my $post = substr( $str, $+[0], $context );
    my $match = substr( $str, $-[0], $+[0] - $-[0] );
    $pre =~ s/.*\n//s;
    $post =~ s/\n.*//s;
    push @results, "$pre$match$post";
}
print for @results;
use strict; 
use warnings; 
my $str = "In this example, A plus B equals C, D plus E "
        . "plus F equals G and H plus I plus J plus K equals L"; 
my $word = "plus"; 
my $chars = 2;
my @results = ();

push @results, $1 
  while $str =~ /(?=((.{0,$chars}?\b$word\b).{0,$chars}))\2/g;

print "'$_'\n" for @results;