代码之家  ›  专栏  ›  技术社区  ›  tjwrona1992

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

  •  0
  • tjwrona1992  · 技术社区  · 7 年前

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

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

    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

    1 回复  |  直到 7 年前
        1
  •  0
  •   ikegami Gilles Quénot    7 年前

    你试着匹配 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;
    }