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

Bash HereDoc标记词正则捕获异常:为何仅匹配OF而非EOF?

Bash HereDoc标记词正则匹配问题解析

问题场景

Bash里HereDoc的开头通常是cat <<EOF或cat << EOF,即<<和标记词(比如EOF)之间可带空格也可不带。想用PCRE正则^\s*cat.*[^<]<{2}[^<](.*)捕获标记词,但测试发现:当<<和EOF之间无空格时,只能捕获到OF而非完整的EOF;同时需要确保正则只匹配恰好两个<,不能匹配三个及以上的情况。

问题原因

你的正则里[^<]<{2}[^<]这部分是核心问题:

  1. .*是贪婪匹配,会尽可能多吃掉字符,直到后面的[^<]<{2}能匹配。处理cat <<EOF时,.*会匹配到cat ,接着[^<]匹配这个空格,<{2}匹配<<。
  2. 此时后面的[^<]会匹配<<之后的第一个字符E(因为E不是<,符合[^<]的规则),导致捕获组(.*)只能拿到剩下的OF,相当于第一个字符被“吃掉”了。
  3. 原正则也没限制三个及以上<的情况,比如cat <<<EOF会被错误匹配——[^<]<{2}会直接匹配最后两个<,忽略第一个。

修正后的正则

要实现仅匹配恰好两个<,同时完整捕获标记词,可以用以下正则:

^\s*cat.*?(?<!<)<{2}(?!<)\s*(.*)

各部分解释

  • ^\s*cat:匹配行首可选空格后的cat关键字
  • .*?:非贪婪匹配,避免吃掉后面的<,直到找到符合条件的<<
  • (?<!<)<{2}(?!<):
    • (?<!<):负向回顾后发断言,确保<<前面不是<,避免匹配<<<中的后两个<
    • <{2}:匹配恰好两个<
    • (?!<):负向先行断言,确保<<后面不是<,避免匹配<<<的情况
  • \s*:匹配<<和标记词之间的可选空格
  • (.*):捕获标记词(如果需要限制标记词格式,比如只能是大写字母,可以改成([A-Z]+))

测试验证

  • 对于cat <<EOF:会完整捕获EOF
  • 对于cat << EOF:会完整捕获EOF
  • 对于cat <<<EOF:不会匹配,因为存在三个<
  • 对于cat x<<EOF:也能正确匹配并捕获EOF

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 11:00:10