我正试图在特定单词之前捕获网址。唯一的麻烦是这个词也可能是域名的一部分。
示例:(我想在晚餐前捕捉所有东西)
https://breakfast.example.com/lunch/dinner/ https://breakfast.example.brunch.com:8080/lunch/dinner http://dinnerdemo.example.com/dinner/
我可以使用:
^(.*://.*/)(?=dinner/?)
我遇到的麻烦是前瞻性似乎不够懒惰 所以以下是失败的:
https://breakfast.example.com/lunch/dinner/login.html?returnURL=https://breakfast.example.com/lunch/dinner/
抓住:
https://breakfast.example.com/lunch/dinner/login.html?returnURL=https://breakfast.example.com/lunch/
我都不明白为什么以及如何修复我的正则表达式。 也许我走错了路,但我怎么能抓住我的所有例子?
答案 0 :(得分:4)
你可以使用一些懒惰:
^(.*?:\/\/).*?/(?=dinner/?)
通过在正则表达式中间使用.*
,您可以吃掉所有内容,直到找到匹配项的最后一个冒号。
.*
是非常糟糕的做法。它可能会导致长串中可怕的回溯性能下降。 .*?
更好,因为它不情愿而不是贪婪。
答案 1 :(得分:4)
前瞻不一定是懒惰的,前瞻只是一个检查,在你的情况下是一个准固定的字符串。
你需要做什么懒惰显然是前瞻之前的子模式。
^https?:\/\/(?:[^\/]+\/)*?(?=dinner(?:\/|$))
注意:(?:/|$)
就像一个边界,确保单词“dinner”后面跟一个斜杠或字符串的结尾。
答案 2 :(得分:1)
您的主要缺陷是使用贪婪匹配.*
与非贪婪.*?
。
以下使用perl执行您想要的匹配,但正则表达式可以很容易地应用于任何语言。请注意在晚餐时使用字边界,这可能是你想要的,也可能不是你想要的:
use strict;
use warnings;
while (<DATA>) {
if (m{^(.*?://.*?/.*?)(?=\bdinner\b)}) {
print $1, "\n";
}
}
__DATA__
https://breakfast.example.com/lunch/dinner/
https://breakfast.example.brunch.com:8080/lunch/dinner
http://dinnerdemo.example.com/dinner/
输出:
https://breakfast.example.com/lunch/
https://breakfast.example.brunch.com:8080/lunch/
http://dinnerdemo.example.com/
答案 3 :(得分:1)
另一种方式。
# Multi-line optional
# ^(?:(?!://).)*://[^?/\r\n]+/(?:(?!dinner)[^?/\r\n]+/)*(?=dinner)
^ # BOL
(?:
(?! :// )
.
)*
://
[^?/\r\n]+ # Domain
/
(?:
(?! dinner ) # Dirs ?
[^?/\r\n]+
/
)*
(?= dinner )
https://breakfast.example.com/lunch/
晚餐/
https://breakfast.example.brunch.com:8080/lunch/
晚餐
http://dinnerdemo.example.com/
晚餐/
https://breakfast.example.com/lunch/
晚餐/ login.html的?RETURNURL = https://breakfast.example.com/lunch/dinner/
答案 4 :(得分:0)
使用 python 3.7
import re
s = '''
https://breakfast.example.com/lunch/dinner/
https://breakfast.example.brunch.com:8080/lunch/dinner
http://dinnerdemo.example.com/dinner/
'''
pat = re.compile(r'.*(?=dinner)', re.M)
mo = re.findall(pat, s)
for line in mo:
print(line, end=' ')
打印输出:
https://breakfast.example.com/lunch/
https://breakfast.example.brunch.com:8080/lunch/
http://dinnerdemo.example.com/