为什么我的Perl正则表达式会导致无限循环?

4
我有一些代码可以抓取文本的“之间”部分;具体来说,是在foo $someword和下一个foo $someword之间。
然而,问题在于它会卡在第一个“之间”,并且内部字符串位置似乎没有增加。
输入数据是一个带有换行符的文本文件:它们不太相关,但使打印更容易。
my $component = qr'foo (\w+?)\s*?{';

while($text =~ /$component/sg)
{
    push @baz, $1; #grab the $someword
}

my $list = join( "|", @baz);
my $re = qr/$list/; #create a list of $somewords

#Try to grab everything between the foo $somewords; 
# or if there's no $foo someword, grab what's left.

while($text=~/($re)(.+?)foo ($re|\z|\Z)/ms)   
#if I take out s, it doesn't repeat, but nothing gets grabbed.
{
#   print pos($text), "\n";   #this is undef...that's a clue I'm certain.
    print $1, ":", $2; #prints the someword and what was grabbed.
    print "\n", '-' x 20, "\n";
}

2
你不想在第二个循环中也加入“/g”修饰符吗? - jrockway
\z 和 \Z 在编程中不是必需的,\Z 包含 \z。 - Chas. Owens
我正在遍历文本,而不是获取数组(这就是/g会返回的内容)。然而,/g并不影响最终输出问题。我已经尝试过了。 :-) - Paul Nathan
1
@chas:将其修改为 \Z 并添加 \g 使其循环一次。删除 \g 可使其无限循环。 - Paul Nathan
1个回答

4

更新: 另外一个更新用于处理想要提取的文本中出现'foo'的情况:

use strict;
use warnings;

use File::Slurp;

my $text = read_file \*DATA;

my $marker = 'foo';
my $marker_re = qr/$marker\s+\w+\s*?{/;

while ( $text =~ /$marker_re(.+?)($marker_re|\Z)/gs ) {
    print "---\n$1\n";
    pos $text -= length $2;
}

__DATA__
foo one {
one1
one2
one3

foo two
{ two1 two2
two3 two4 }

that was the second one

foo three { 3
foo 3 foo 3
foo 3
foo foo

foo four{}

输出:

---
一个1 一个2 一个3
--- 两个1 两个2 两个3 两个4 }
那是第二个
--- 3 foo 3 foo 3 foo 3 foo foo
--- }

关于这个问题,是的。我正在寻找大括号后面和下一个foo之前的所有内容。 - Paul Nathan
那个可行。 如果没有 $text -= 3 这一行,它会返回第一个和最后一个。 我很困惑你的解决方案为什么有效以及我的解决方案有什么问题。你有什么想法吗? - Paul Nathan
寻找 (?:foo|\Z) 会在存在 foo 的情况下将 pos $text 推进 foo 的长度。 因此,下一个匹配从下一个 foo 开始,除非 pos $text 被重置到当前位置之前三个字符的位置上。 如果已经到达字符串的末尾,则不影响这一过程。 - Sinan Ünür
1
@Sinan:我注意到如果有一个my $foomatic,正则表达式会匹配'foo'。我修改了我的正则表达式为\bfoo\b。:-) 非常感谢你的帮助。 - Paul Nathan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接