我需要一些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 plus B D plus E E plus F H plus I I plus J J plus K
如何更改正则表达式以获得此结果?谢谢---丹
答案 0 :(得分:6)
一般建议:如果需要s///
,请勿使用m//
。具体在你匹配的内容。
答案是pos
:
#!/usr/bin/perl -l
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 =~ /([A-Z] $word [A-Z])/g ) {
push @results, $1;
pos($str) -= 1;
}
print "'$_'" for @results;
输出:
C:\Temp> b 'A plus B' 'D plus E' 'E plus F' 'H plus I' 'I plus J' 'J plus K'
答案 1 :(得分:3)
您可以使用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;
答案 2 :(得分:2)
另一个选择是使用前瞻:
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
匹配“实际”任何由第2组捕获的内容,这与第1组相同,除了它在单词的结尾处停止。这会将pos
设置在您想要的位置,而无需计算您在单词后实际匹配的字符数。
答案 3 :(得分:1)
鉴于“完全披露”评论(但假设是.{0,35}
,而不是.{35}
),我会做
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;
如果你的意思是(?s:.{0,35})
,你会跳过替换。
答案 4 :(得分:0)
这是一种方法:
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-ish,但是它有效并且它不会使用太多模糊的正则表达技巧。但是,您可能必须在perlvar
中查找特殊变量@-
的功能。
答案 5 :(得分:0)
不必使用正则表达式。基本上,只需分割字符串,使用循环遍历每个项目,检查“加号”,然后从前后获取单词。
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";
}
}