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

preg_match_all匹配Markdown链接异常:多匹配被合并为单个

解决preg_match_all匹配Markdown链接时的贪婪匹配问题

嘿,我完全懂你遇到的麻烦!你用的正则/\]\(.*.md\)/之所以没正确识别出第二个链接,核心原因就是正则的贪婪匹配特性——.*会尽可能匹配最长的字符串,从第一个](开始,它会一直吃到最后一个.md)之前的所有内容,把中间的| [example2](other/some.md都包含进去了,自然就漏掉了第二个独立的链接。

两种可行的修复方案

1. 使用非贪婪量词.*?

把原来的.*改成.*?,这样正则会匹配最短的符合条件的字符串,而不是最长的。同时注意把.md里的.转义成\.(因为.在正则里是通配符,会匹配任意字符,转义后才代表真正的点号):

$markdownContent = '[example](foo/random/link.md) | [example2](other/some.md) Lorem ipsum..... [example3](foo/Readme.md)';
preg_match_all('/\]\(.*?\.md\)/', $markdownContent, $matches);
print_r($matches[0]);

执行后你会得到3个正确的匹配结果:

Array
(
    [0] => ](foo/random/link.md)
    [1] => ](other/some.md)
    [2] => ](foo/Readme.md)
)

2. 使用排除型字符集(更高效)

如果你确定Markdown链接的路径里不会包含),可以用[^)]+代替.*?,它表示匹配除了)之外的所有字符,这样不需要依赖非贪婪匹配,性能更好,也更精准:

preg_match_all('/\]\([^)]+\.md\)/', $markdownContent, $matches);

这个正则的效果和上面的非贪婪版本完全一致,但避免了正则引擎的回溯操作,处理大文档时速度会更快。

针对你的需求优化:提取链接路径本身

既然你要把链接转换成相对路径,肯定需要单独拿到括号里的路径部分,而不是包含](的完整匹配。可以给路径部分加个捕获组,这样直接从$matches[1]里取路径:

preg_match_all('/\]\((.*?\.md)\)/', $markdownContent, $matches);
// $matches[1] 就是你需要的路径数组
print_r($matches[1]);

输出结果:

Array
(
    [0] => foo/random/link.md
    [1] => other/some.md
    [2] => foo/Readme.md
)

这样你就可以直接遍历这个数组,对每个路径做相对转换的处理了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:00:09