Regex Perl正则表达式如何在下一个匹配中重复使用上一个匹配的一部分?
我需要一些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
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 thansubstr
。感谢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;