懒惰量词和向前看

问题描述:

我正在使用C#验证网址的正则表达式。现在,我需要的正则表达式不能与其他http://匹配,但是它是url中的第一个。这是我第一次尝试:懒惰量词和向前看

(https?:\/\/.+?)\/(.+?)(?!https?:\/\/) 

但这正则表达式不工作(甚至消除(?!https?:\/\/))。就拿这个输入字符串:

http://test.test/notwork.http://test 

这是我的第一个疑问:为什么不捕获组(.+?)比赛notwork.http://test?懒惰的量词应该尽可能少地匹配,但为什么不直到最后呢?在这种情况下,我肯定错过了一些东西(首先我认为它可能与回溯有关,但我不认为是这种情况),所以我读this并找到了解决方案,即使我不确定是否是最好的因为它说,

该技术存在任何优势来相会点星级

总之,该解决方案是回火点。这是我的下一个尝试:

(https?:\/\/.+?)\/((?:(?!https?:\/\/).)*) 

现在:这个正则表达式工作,但不是我想要的方式。 只有当网址有效时,我才需要一个匹配。

顺便说一句,我想我已经不能充分理解新的正则表达式是这样做的:为什么负先行的.前停留,而不是之后呢? 所以我试图在.之后移动它,它似乎匹配url直到找到第二个http之前的倒数第二个字符。回到正确的正则表达式,我的假设是负面的前瞻实际上是试图检查.已经读过的正则表达式,这是正确的吗?

其他解决方案已被广泛接受,但我首先更愿意理解这一点。谢谢。

+0

这个问题太广泛了。第二个“怀疑”在[这里]解释(https://*.com/questions/30900794/tempered-greedy-token-what-is-different-about-placing-the-dot-before-the-negat)。至于第一个,你只需要使用* positive * lookahead和''''替代('(。*?)(?= https?:\/\/| $)')。一个'。+?'匹配1个字符,并且不需要匹配更多,因为它是懒惰的。 –

+0

你是什么意思“只有当网址有效时我需要一个匹配”? –

+0

关于第一个疑问:我应该使用'$',这样懒惰的量词可以匹配直到输入结束,对吗?为什么没有暗示?我读到你的回答关于脾气暴躁的标记*,它肯定更清楚。只有当url不包含其他'http://'时,我才需要一个匹配,而当我使用当前的正则表达式时,如果包含'http://',我也有匹配。顺便说一句,谢谢你的答案。 –

你所寻求的解决方案是

(?>https?://\S+?/(?:(?!https?://).)*)(?!https?://) 

regex demo

详细

  • (?>https?://\S+?/(?:(?!https?://).)*) - 的原子团(允许无回溯到它的子模式)匹配
    • https?:// - http://https://
    • \S+? - 任何1个或多个非空白字符,尽可能少,直至第一...
    • / - /符号随后与...
    • (?:(?!https?://).)* - 零个或多个字符(尽可能多),它们不会启动一系列http://https://字符。
  • (?!https?://) - 负先行失败的比赛,如果有http://https://立即到当前位置的右侧。

(https?:\/\/.+?)\/(.+?)(?!https?:\/\/)因为.+?图案匹配懒惰地不工作,即它抓住它找到的第一个字符,然后让后续子模式匹配。随后的子模式是仅在当前位置右侧没有http://https://的情况下才失败匹配的负面loolahead。由于在http://test.test/notwork.http://test中的n之后没有这样的子字符串,所以以n结尾的匹配被返回,所以匹配成功。如果您不告诉正则表达式引擎匹配更多,或者直到其他分隔符/模式,它不会。

脾气暴躁的标记解决方案已被讨论了很多。 this answer中涵盖了确切的怀疑在何处放置预览。