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

9
在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进行此操作,因此将使用它们的正则表达式引擎。


你会使用哪个正则表达式引擎/语言? - Casimir et Hippolyte
Python的!抱歉,应该先澄清一下,现在会编辑问题。 - Sam Kellett
4
细节问题,但是您的 Markdown 方括号顺序错误——应该是 [文本](链接),因此 []()之前。 - Hamish Downer
还有一种通过引用添加链接的方式,例如在一行中使用[link],然后在其他地方使用[link]: http://... - Jorge Orpinel Pérez
1个回答

10
你的模式无法工作的原因在于这里:(?<=\((.*)\)\[),因为Python的re模块不允许可变长度的正向回顾。你可以使用Python的新正则表达式模块regex来更加方便地获得你想要的结果(因为相比之下,re模块的功能较少)。例如:(?|(?<txt>(?<url>(?:ht|f)tps?://\S+(?<=\P{P})))|\(([^)]+)\)\[(\g<url>)\])。这是一个在线演示:http://regex101.com/r/mL3hA8/1。模式细节如下:
(?|                                       # 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}


@Unihedron:ftps不是由IETF(http://en.wikipedia.org/wiki/Internet_Engineering_Task_Force)处理的,但这是可能的。 - Casimir et Hippolyte
1
有没有标准的Python Markdown库可以允许检索链接?这似乎比自己编写复杂的正则表达式更好。 - automaciej
它不匹配[foo](#some-internal-link),也不匹配没有空格的网址(如[foo](http://bla.com).[bla](http://ddd.com))。添加句点后面的空格即可匹配。您能解决这个问题吗? - somenxavier
@somenxavier:你在示例中颠倒了方括号和圆括号。关于内部链接,没有任何禁止构建更具描述性或更宽松的子模式用于URL的规定。我在示例中使用的是最小化的模式,不能处理所有类型的URL。(请注意,处理所有URL的模式只有一页长)。 - Casimir et Hippolyte

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接