我的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
答案 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
。