正则表达式初始(匹配中的匹配)

时间:2017-09-27 20:57:58

标签: regex perl regex-lookarounds regex-group

我正在尝试创建一个捕获命名组的正则表达式,然后在该命名组中查看它是否包含某些特性。

例如。我有一个匹配代码块的正则表达式,我可以使用它来匹配和捕获代码块:

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

我错过了什么?

1 个答案:

答案 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;
}