JavaScript如何从字符串指定位置匹配正则校验Markdown标题
问题原因
你的代码返回错误结果的核心原因是正则逻辑存在漏洞:
- 你开启了正则的
m多行匹配模式,该模式下^不仅能匹配整个字符串的起始位置,还能匹配任意换行符\n之后的行首位置 - 正则中
^[^]{${startPos}}部分仅要求累计匹配startPos个任意字符,但后续分组里的^#+会触发正则引擎自动搜索文本中所有符合的行首位置,完全没有约束#序列必须 刚好从startPos位置开始 - 当startPos=0时,
[^]{0}匹配空字符串,引擎会直接跳过开头的abc\n,匹配到第4位的##序列,因此错误返回true。另外这种拼接可变长度匹配的正则,在startPos数值较大时性能会非常差。
修复方案
不需要构造复杂的动态正则,直接按规则分步校验逻辑更清晰、性能更稳定:
- 先做边界判断,起始位置超出文本长度直接返回false
- 校验起始位置必须是行首:要么是字符串0位置,要么前一个字符是换行符
- 截取起始位置之后的子串,用固定正则严格校验子串开头是否符合Markdown标题规则(1个及以上
#,后接至少1个空白字符,再跟标题内容)
注:标准Markdown的ATX标题最多支持6个
#,如果你的业务不需要该限制,可以把正则里的{1,6}替换为+即可。
修复后的完整代码:
function isMarkdownHeader(text, startPos) { // 起始位置非法直接返回false if (startPos < 0 || startPos >= text.length) return false; // 校验当前位置必须是行首 if (startPos > 0 && text[startPos - 1] !== '\n') return false; // 校验子串开头符合标题规则 const headerReg = /^#{1,6}\s+.*/; return headerReg.test(text.slice(startPos)); } // 测试用例验证 console.log(isMarkdownHeader("abc\n## My Title\nxyz", 4)); // true console.log(isMarkdownHeader("abc\n## My Title\nxyz", 0)); // false,符合预期 console.log(isMarkdownHeader("abc\n# My Title", 4)); // true console.log(isMarkdownHeader("abc\n# My Title\nxyz", 4)); // true console.log(isMarkdownHeader("abc\n#My Title", 0)); // false
内容的提问来源于stack exchange,提问作者Searene
相关产品推荐
相关产品推荐

