re.search() 中的非贪婪模式与字符串结尾不匹配
Non-greedy mode in re.search() does not match to end of string
我正在尝试像这样解析 cookie 的值:
import re
m = re.search("(.*?)=(.*?); path=(.*?); domain=(.*?)", "name=value1; path=/; domain=my.domain.com")
print (m.group(0))
我得到的结果是这样的:
name=value1; path=/; domain=
我的问题是:为什么在最后一个非贪心位置不匹配?预期结果为:
name=value1; path=/; domain=my.domain.com
当然,我可以更改为贪婪模式或使用行尾字符 ($
),但我想了解为什么它没有像我预期的那样工作:)
非贪婪意味着它会尽可能少地匹配,同时仍然允许整个匹配成功。 *
表示 "zero or more"。所以它至少可以匹配为零。所以它匹配零,匹配成功。
您的正则表达式中 .*?
的其他出现不能匹配零,因为这样整个正则表达式将无法匹配。
您的最后一个 (.*?)
匹配的字符越少越好。要匹配 cookie 的其余部分,您必须设置先行,或匹配已知字符。
这是一个前瞻性解决方案:
(.*?)=(.*?); path=(.*?); domain=(.*?)(?=;\s|$)
见demo
顺便说一句,regex101 非常有助于了解正则表达式幕后的要点:转到 regex debugger 并单击右侧的 +
,你会看到当你的正则表达式到达最后一个 (.*?)
:
时到底发生了什么
所以,就是我一开始说的:匹配越少越好。它匹配 =
符号后的空字符串,其余可以是 "given away" 因为这是 lazy matching 所做的。
The standard quantifiers in regular expressions are greedy, meaning
they match as much as they can, only giving back as necessary to match
the remainder of the regex.
By using a lazy quantifier, the expression tries the minimal match
first.
其他答案很好地解释了为什么您的代码无法按原样运行。我只是指出,老实说,您应该贪婪地匹配非 space 字符,而不是非贪婪地匹配所有字符。
re_obj = re.compile(r"""
(\S*)=(\S*);\s* # capture unknown key/value pair
path=(\S*);\s* # capture path
domain=(\S*) # capture domain""", re.X)
演示
>>> result = re_obj.search("name=value1; path=/; domain=my.domain.com")
>>> result.groups()
('name', 'value1', '/', 'my.domain.com')
更重要的是,这似乎比字符串操作更容易
txt = "name=value1; path=/; domain=my.domain.com"
parameters = {key.strip(): value.strip() for parm in txt.split(';') for
key,value in (parm.strip().split('='),)}
我正在尝试像这样解析 cookie 的值:
import re
m = re.search("(.*?)=(.*?); path=(.*?); domain=(.*?)", "name=value1; path=/; domain=my.domain.com")
print (m.group(0))
我得到的结果是这样的:
name=value1; path=/; domain=
我的问题是:为什么在最后一个非贪心位置不匹配?预期结果为:
name=value1; path=/; domain=my.domain.com
当然,我可以更改为贪婪模式或使用行尾字符 ($
),但我想了解为什么它没有像我预期的那样工作:)
非贪婪意味着它会尽可能少地匹配,同时仍然允许整个匹配成功。 *
表示 "zero or more"。所以它至少可以匹配为零。所以它匹配零,匹配成功。
您的正则表达式中 .*?
的其他出现不能匹配零,因为这样整个正则表达式将无法匹配。
您的最后一个 (.*?)
匹配的字符越少越好。要匹配 cookie 的其余部分,您必须设置先行,或匹配已知字符。
这是一个前瞻性解决方案:
(.*?)=(.*?); path=(.*?); domain=(.*?)(?=;\s|$)
见demo
顺便说一句,regex101 非常有助于了解正则表达式幕后的要点:转到 regex debugger 并单击右侧的 +
,你会看到当你的正则表达式到达最后一个 (.*?)
:
所以,就是我一开始说的:匹配越少越好。它匹配 =
符号后的空字符串,其余可以是 "given away" 因为这是 lazy matching 所做的。
The standard quantifiers in regular expressions are greedy, meaning they match as much as they can, only giving back as necessary to match the remainder of the regex.
By using a lazy quantifier, the expression tries the minimal match first.
其他答案很好地解释了为什么您的代码无法按原样运行。我只是指出,老实说,您应该贪婪地匹配非 space 字符,而不是非贪婪地匹配所有字符。
re_obj = re.compile(r"""
(\S*)=(\S*);\s* # capture unknown key/value pair
path=(\S*);\s* # capture path
domain=(\S*) # capture domain""", re.X)
演示
>>> result = re_obj.search("name=value1; path=/; domain=my.domain.com")
>>> result.groups()
('name', 'value1', '/', 'my.domain.com')
更重要的是,这似乎比字符串操作更容易
txt = "name=value1; path=/; domain=my.domain.com"
parameters = {key.strip(): value.strip() for parm in txt.split(';') for
key,value in (parm.strip().split('='),)}