You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Perl6语法匹配Markdown标题时贪婪匹配问题求助

这个问题的核心在于你的span正则是贪婪匹配的,它会把所有符合<like-a-word>规则的内容(包括末尾的##)都吞掉,导致后面的[\h* $0]?完全没有机会触发匹配——毕竟##是\S+,完美符合<like-a-word>的定义。

要解决这个问题,我们需要让span在遇到行尾的闭合哈希序列时停下来,也就是让它匹配到可选的闭合哈希之前的内容。这里有两种比较优雅的调整方式:

方法一:利用动态变量+先行断言限制span的匹配范围

我们可以在header里把开头捕获到的哈希序列存在动态变量中,然后让span的正则通过先行断言,确保它不会把行尾的闭合哈希包含进去:

role Like-a-word { regex like-a-word { \S+ } }
role Span does Like-a-word { 
    regex span { 
        <like-a-word> 
        [\s+ <like-a-word>]*?  # 改成非贪婪匹配,给后面的闭合哈希留机会
        <!before \h* $*HASHES $$>  # 断言当前位置后不是行尾的闭合哈希
    } 
}
grammar Grammar::Headers does Span {
    token TOP {^ <header> \v+ $}
    token hashes { '#'**1..6 }
    regex header {
        ^^ 
        <hashes> 
        { $*HASHES = $<hashes> }  # 把开头的哈希序列存到动态变量里
        \h+ 
        <span> 
        [\h* $0]?  # 现在这个部分就能正常匹配末尾的闭合哈希了
        $$
    }
}

方法二:直接重构header的正则结构

如果不想用动态变量,也可以直接在header里调整匹配顺序,用非贪婪匹配捕获标题内容,再让闭合哈希的匹配优先:

role Like-a-word { regex like-a-word { \S+ } }
role Span does Like-a-word { regex span { <like-a-word>[\s+ <like-a-word>]* } }
grammar Grammar::Headers does Span {
    token TOP {^ <header> \v+ $}
    token hashes { '#'**1..6 }
    regex header {
        ^^ 
        <hashes> 
        \h+ 
        ( <like-a-word> ( \s+ <like-a-word> )*? )  # 非贪婪匹配标题内容
        ( \h* $0 )?  # 优先匹配闭合哈希
        $$
        { make $0 => $1 }  # 可选:把结果整理成更清晰的结构
    }
}

测试效果

现在再匹配## Easier ##,你会看到:

  • hashes捕获到开头的##
  • span(或第二个捕获组)捕获到Easier
  • 末尾的##会被[\h* $0]?正确捕获,而不是被span吃掉

这样就完美符合Markdown标题的匹配规则了。

内容的提问来源于stack exchange,提问作者jjmerelo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:23:59