如何用正则表达式找到所有Markdown链接?

9 投票
1 回答
4886 浏览
提问于 2025-04-18 15:51

在Markdown中,有两种方式可以插入链接,一种是直接输入链接,比如:http://example.com,另一种是使用()[]的语法:(Stack Overflow)[http://example.com]

我正在尝试写一个正则表达式,能够匹配这两种情况,并且如果是第二种情况,还能提取出显示的文本。

到目前为止,我有这个:

(?P<href>http://(?:www\.)?\S+.com)|(?<=\((.*)\)\[)((?P=href))(?=\])

正则表达式可视化

Debuggex演示

但是这似乎没有匹配我在Debuggex中测试的两个案例:

http://example.com
(Example)[http://example.com]

我真的不明白为什么至少第一个没有匹配,是不是和我使用的命名组有关?如果可以的话,我希望继续使用,因为这是一个简化的表达式,用来匹配链接,而在实际例子中,这个表达式太长了,我不太想在同一个模式中重复两次。

我哪里做错了?还是说这根本就做不到?

编辑:我是在Python中做这个,所以会使用他们的正则表达式引擎。

相关问题:

1 个回答

10

你遇到的问题在于这个部分:(?<=\((.*)\)\[),因为Python的re模块不支持可变长度的回顾。

你可以用一种更方便的方法来实现你的需求,使用Python的新regex模块 (因为re模块的功能比较少)

举个例子:(?|(?<txt>(?<url>(?:ht|f)tps?://\S+(?<=\P{P})))|\(([^)]+)\)\[(\g<url>)\])

这是一个在线演示

模式细节:

(?|                                       # open a branch reset group
    # first case there is only the url
    (?<txt>                               # in this case, the text and the url  
        (?<url>                           # are the same
            (?:ht|f)tps?://\S+(?<=\P{P})
        )
    )
  |                                       # OR
    # the (text)[url] format
    \( ([^)]+) \)                         # this group will be named "txt" too 
    \[ (\g<url>) \]                       # this one "url"
)

这个模式使用了分支重置功能(?|...|...|...),可以在选择中保留捕获组的名称(或编号)。在这个模式中,由于?<txt>组在选择的第一个部分被打开,所以第二部分的第一个组会自动使用相同的名称。?<url>组也是如此。

\g<url>是对命名子模式?<url>的引用(就像一个别名,这样在第二部分就不需要重复写了)。

(?<=\P{P})用来检查url的最后一个字符是否不是标点符号(这对于避免闭合方括号很有用)。(我不太确定这个语法,可能是\P{Punct})

撰写回答