我正在尝试创建一个捕获命名组的正则表达式,然后在该命名组中查看它是否包含某些特性。
例如。我有一个匹配代码块的正则表达式,我可以使用它来匹配和捕获代码块:
test.pl:
use strict;
use warnings;
my $text = <<'END_TEXT';
block {
// random stuff
}
block {
dog
}
END_TEXT
my $code_block_rx = qr{(?(DEFINE)
(?<code_block>
block\h\{ (?: [^{}]++ | (?&code_block) )*+ \}
)
)}xms;
while ($text =~ m/(?<match>(?&code_block))$code_block_rx/g) {
print $+{match}."\n";
}
此代码将打印两个代码块。但是,如果我只想捕获包含单词&#34; dog&#34;?
的代码块,该怎么办?是否有方法(在单个正则表达式中)捕获代码块,然后如果找到,请在代码块中查找单词&#34; dog&#34;?
我尝试修改正则表达式以使用前瞻断言,但它只会导致整个事情失败:/(?<match>(?=dog)(?&code_block))$code_block_rx/g
我错过了什么?
答案 0 :(得分:0)
您尝试在匹配开始的位置匹配dog
。
相反,您可以检查它是否在匹配的块中。
while ($text =~ /(
\b block \h*+ ( (?&code_block) )
(?(DEFINE)
(?<code_block> \{ (?&code_block_body) \} )
(?<code_block_body> (?: [^{}]++ | (?&code_block) )*+ )
)
)/xg) {
my $block_stmt = $1;
my $block_stmt_block = $2;
if ($block_stmt_block =~ /\b dog \b/x) {
say $block_stmt;
}
}
可以使用(?(?{!( assertion() )})(*FAIL))
匹配您已捕获的内容,以单一模式完成。
while ($text =~ m{(
\b block \h*+
# A code_block that contains the word 'dog'.
( (?&code_block) ) (?(?{!( "$^N" =~ /\b dog \b/x )})(*FAIL))
(?(DEFINE)
(?<code_block> \{ (?&code_block_body) \} )
(?<code_block_body> (?: [^{}]++ | (?&code_block) )*+ )
)
)}xg) {
say $1;
}