Python正则表达式 - 完全匹配

时间:2010-09-08 15:18:14

标签: python regex

我的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'这样的完整比赛。我可以假设一组的第一场比赛总是最完整的吗?或者是否有一个标志告诉重新显示最完整的匹配?

的Stefan

3 个答案:

答案 0 :(得分: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返回的第一个匹配应该是完全匹配的子字符串。

答案 1 :(得分:2)

将你的内心群体(即括号)变成 - 捕获的群体:即改变自:

(([a-z]{1,8})(-[a-z]{1,8})*)

为:

((?:[a-z]{1,8})(?:-[a-z]{1,8})*)

总结一下,模式符号(?: ... )定义了一个 - 捕获组:括号仍然用于控制优先级,但不要在匹配对象的{{ 1}}和其他捕获组相关的特征。

普通括号.groups()表示捕获组。

当然,没有理由将捕获组用于您明确感兴趣的子匹配。仅将它们用于执行关注的子匹配! - )

答案 2 :(得分:0)

不确定你是否已经检查过它,但是this article有许多关于进行Accept-Language解析的好指示,以及对已经解决问题的库的引用。

就你的re问题而言,Doug Hellman在他最近的本周Python模块中有一个great breakdown of re