我还在学习Perl,如果这是一个显而易见的问题,请道歉。 有没有办法匹配括号内未包含的文本? 例如,搜索foo只会匹配第二行。
(bar foo bar)
bar foo (
bar foo
(bar) (foo)
)
答案 0 :(得分:5)
正则表达式模式具有隐式前导\G(?s:.)*?
("跳过字符直到找到匹配")。以下内容扩展了该定义,以将嵌套的parens视为要跳过的字符。
while (
$string =~ m{
\G (?&MEGA_DOT)*?
( foo )
(?(DEFINE)
(?<MEGA_DOT> [^()] | \( (?&MEGA_DOT)*+ \) )
)
}xg
) {
say "Found a match at pos $-[1].";
}
答案 1 :(得分:4)
这离&#34;很明显&#34 ;;反之。没有直接的方式可以说'#34;不匹配&#34;对于复杂的模式(在角色级别有良好的支持,[^a]
,\S
等)。正则表达式首先是关于匹配事物,而不是关于不匹配它们。
一种方法是匹配那些(可能是嵌套的)分隔符并获得除此之外的所有内容。
查找嵌套分隔符的好工具是核心模块Text::Balanced。在匹配时,它还可以在匹配之前为我们提供子字符串,在匹配之后为字符串的其余部分提供。
use warnings;
use strict;
use feature 'say';
use Text::Balanced qw(extract_bracketed);
my $text = <<'END';
(bar foo bar)
bar foo (
bar foo
(bar) (foo)
)
END
my ($match, $before);
my $remainder = $text;
while (1) {
($match, $remainder, $before) = extract_bracketed($remainder, '(', '[^(]*');
print $before // $remainder;
last if not defined $match;
}
extract_bracketed
返回匹配,余数子串($remainder
)和匹配前的子字符串($before
);所以我们在其余部分保持匹配。
取自this post,其中有更多详情和其他方式,使用Regexp::Common。