正则表达式开始(一场比赛中的一场比赛)
Regular Expression Inception (a match within a match)
我正在尝试创建一个正则表达式来捕获命名组,然后在该命名组中查找以检查它是否包含某些特性。
例如。我有一个匹配代码块的正则表达式,我可以用它来匹配和捕获代码块:
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";
}
此代码将打印两个代码块。但是,如果我只想捕获包含单词 "dog" 的代码块怎么办?
有没有办法(在单个正则表达式中)捕获代码块,如果找到,则在代码块中查找单词 "dog"?
我尝试修改正则表达式以使用前瞻断言,但这只会导致整个事情失败:/(?<match>(?=dog)(?&code_block))$code_block_rx/g
我错过了什么?
您试图在匹配开始的位置匹配 dog
。
相反,您可以检查它是否在您匹配的块中。
while ($text =~ /(
\b block \h*+ ( (?&code_block) )
(?(DEFINE)
(?<code_block> \{ (?&code_block_body) \} )
(?<code_block_body> (?: [^{}]++ | (?&code_block) )*+ )
)
)/xg) {
my $block_stmt = ;
my $block_stmt_block = ;
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 ;
}
我正在尝试创建一个正则表达式来捕获命名组,然后在该命名组中查找以检查它是否包含某些特性。
例如。我有一个匹配代码块的正则表达式,我可以用它来匹配和捕获代码块:
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";
}
此代码将打印两个代码块。但是,如果我只想捕获包含单词 "dog" 的代码块怎么办?
有没有办法(在单个正则表达式中)捕获代码块,如果找到,则在代码块中查找单词 "dog"?
我尝试修改正则表达式以使用前瞻断言,但这只会导致整个事情失败:/(?<match>(?=dog)(?&code_block))$code_block_rx/g
我错过了什么?
您试图在匹配开始的位置匹配 dog
。
相反,您可以检查它是否在您匹配的块中。
while ($text =~ /(
\b block \h*+ ( (?&code_block) )
(?(DEFINE)
(?<code_block> \{ (?&code_block_body) \} )
(?<code_block_body> (?: [^{}]++ | (?&code_block) )*+ )
)
)/xg) {
my $block_stmt = ;
my $block_stmt_block = ;
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 ;
}