我正在使用re.match
与python进行相当复杂的匹配,其形式为(some_pattern_1)?(some_pattern_2)?..(.*)
另一方面,我有一个单元测试,我正在检查大约一百个例子,它们都是异步向我的(本地,开发)服务器发送请求。服务器在django。
我有时候看到这场比赛显然是非贪婪的(即最后一次抓住所有区块的事情太多了)并且单元测试失败了,但是不能真正重现它,我不是真的知道发生了什么。
更具体地说,正则表达式的相关部分是(在Python中):
import re
input = "1 small shoe"
sizes = ["small", "large", "big", "huge"]
colors = ["blue", "red", "green", "yellow", "grey"]
anySize = u' |'.join(sizes)
anyColor = u' |'.join(colors)
matched_expression = re.match(
r'\s*(?P<amount>(((\d{1,2}\.)?\d{1,3})?)\s*'
r'(?P<size>(\b'+anySize+'\b)?)\s*'
r'(?P<color>(\b'+anyColor+'\b)?)\s*'
r'(?P<name>.*, input, re.UNICODE|re.IGNORECASE)
if matched_expression:
print(matched_expression.groupdict()["amount"])
print(matched_expression.groupdict()["size"])
print(matched_expression.groupdict()["color"])
print(matched_expression.groupdict()["name"])
我有时会看到这张照片:
1
''
''
'small shoe'
是否存在可能发生这种情况的条件(我认为正则表达式匹配原则上是完全确定的是正确吗?)
答案 0 :(得分:1)
您用于构建模式的大多数字符串文字是原始文字(使用r
前缀引入),这很棒 - 字符串解释器因此不提供反斜杠任何特殊的意义,但相反,它们完整的正则表达式解析器。但是,遗憾的是,在每种情况下都没有使用原始文字:
r'(?P<size>(\b'+anySize+'\b)?)\s*'
# ^^^^^^^^^^ this is not a raw string literal
r'(?P<color>(\b'+anyColor+'\b)?)\s*'
# ^^^^^^^^^^ and nor is this
因此,在将解释的字符串提供给正则表达式编译器之前,这些文字中的反斜杠具有String and Bytes literals下描述的效果。因此,您的\b
边界锚将替换为ASCII退格字符!
使用原始字符串文字,前缀为r
,或者确保转义它们包含的反斜杠。
但是,您的代码还有许多其他问题值得注意:
如目前所写,由于某些语法错误,您的正则表达式将无法编译。特别是,由于括号不平衡,名为amount
和name
的捕获组不会终止:
r'\s*(?P<amount>(((\d{1,2}\.)?\d{1,3})?)\s*'
# + +++ - - -
有四个左括号,但只有三个右括号。你可能打算写:
r'\s*(?P<amount>(((\d{1,2}\.)?\d{1,3})?))\s*'
# ^
同样,r'(?P<name>.*, ...
应该是r'(?P<name>.*)', ...
(注意模式字符串需要在参数分隔符之前终止)。
\b
边界锚点比|
交替更紧密地绑定,因此当放置在与连接数组相同的级别时,它们仅分别绑定到备选项的第一个和最后一个元素。例如,名为size
的捕获组当前由以下模式指定:
(\bsmall |large |big |huge\b)?
在优先级方面,这相当于:
((\bsmall )|(large )|(big )|(huge\b))?
最好将边界锚放在括号之外:
r'(?P<size>\b('+anySize+r')?\b)\s*'
r'(?P<color>\b('+anyColor+r')?\b)\s*'
如上所示,连接表达式中的空格可能会导致意外后果:anySize
和anyColor
要求除了基础数组中的最终项之外的所有项都是(如果存在) ,后跟一个空格字符(除了那些与\s*
模式匹配的字符。最好单独使用'|'
加入数组,而不是' |'
:
anySize = u'|'.join(sizes)
anyColor = u'|'.join(colors)
根据底层数组的来源以及您对它们的信心,它们不包含任何特殊的正则表达式模式,您可能希望首先转义数组元素。