Python正则表达式 - 完全匹配
在我的CGI应用程序中,我正在写一个函数,用来获取浏览器的首选语言,这个信息保存在HTTP_ACCEPT_LANGUAGE这个变量里。我想用正则表达式找到这个变量中的所有语言标签(语言标签的一般格式在RFC1766中有定义)。RFC1766中的EBNF规则('1*8ALPHA'表示一个到八个ASCII字符):
Language-Tag = Primary-tag *( "-" Subtag )
Primary-tag = 1*8ALPHA
Subtag = 1*8ALPHA
我为语言标签写了这个正则表达式:
(([a-z]{1,8})(-[a-z]{1,8})*)
如果我使用这个表达式,Python的re模块会给出以下结果:
>>import re
>>re.findall("(([a-z]{1,8})(-[a-z]{1,8})*)", "x-pig-latin en-us de-de en", re.IGNORECASE)
[('x-pig-latin', 'x', '-latin'), ('en-us', 'en', '-us'), ('de-de', 'de', '-de'), ('en', 'en', '')]
结果是正确的。但是我只需要完整的匹配,比如'de-de'或者'x-pig-latin'。我可以假设一个组的第一个匹配总是最完整的吗?或者有没有什么标志可以让re显示最完整的匹配结果?
Stefan
3 个回答
2
把你内部的括号(也就是小括号)改成不捕获的类型:也就是说,把下面的:
(([a-z]{1,8})(-[a-z]{1,8})*)
改成:
((?:[a-z]{1,8})(?:-[a-z]{1,8})*)
简单来说,模式符号 (?: ... )
定义了一个不捕获的组:这些小括号仍然可以用来控制优先级,但它们不会在匹配结果的 .groups()
和其他与捕获组相关的特性中留下痕迹。
普通的小括号 ( ... )
表示一个捕获组。
当然,对于那些你明确不感兴趣的子匹配,使用捕获组是没有必要的。只对你关心的子匹配使用捕获组!-)
4
你可以使用 ?: 这个操作符来防止正则表达式引擎保存括号里的子模式:
((?:[a-z]{1,8})(?:-[a-z]{1,8})*)
这样会得到以下输出:
re.findall("((?:[a-z]{1,8})(?:-[a-z]{1,8})*)", "x-pig-latin en-us de-de en", re.IGNORECASE)
['x-pig-latin', 'en-us', 'de-de', 'en']
回答你的问题,findall 返回的第一个匹配结果应该是完整的匹配子串。