我有一些字符串包含两个引号之间的信息,例如:
cc "1/11/2A" "1/20+21/1 1" "XX" 0
我re.findall('\"*\"', line)
用来匹配引号之间的部分,但由于某种原因不起作用。我尝试了很多其他的东西,但我得到的只是一些空列表,里面什么都没有。我究竟做错了什么 ?
您正在匹配 0 个或多个引号,后跟一个引号。改用否定字符类:
re.findall(r'"[^"]*"', line)
您可能希望在否定字符类周围放置一个捕获组:
re.findall(r'"([^"]*)"', line)
现在.findall()
返回引号内的所有内容,不包括引号本身:
>>> import re
>>> re.findall(r'"([^"]*)"', 'cc "1/11/2A" "1/20+21/1 1" "XX" 0')
['1/11/2A', '1/20+21/1 1', 'XX']
[^...]
否定字符类表示法意味着:匹配任何不包含在此处命名的字符集中的字符。[^"]
因此匹配任何不是引号的字符,将匹配的字符巧妙地限制为引号内的所有字符。
应该是r'"[^"]*"'
。您的模式匹配一"
行中的一个或多个字符。
In [4]: re.findall(r'"[^"]*"', line)
Out[4]: ['"1/11/2A"', '"1/20+21/1 1"', '"XX"']
看起来您希望*
匹配“任何内容”,就像它在文件名通配符中所做的那样。
但这不是它在正则表达式中的含义。它修改前面的表达式,以匹配该表达式的零个或多个副本。
要获取文件名样式的通配符,您需要使用.*
.
然而,这实际上不起作用,因为.
匹配任何东西——包括"
. 所以,它会抓取最后一个"
字符的所有内容,只留下表达式的其余部分,意思是findall
找到一个大字符串而不是三个小字符串。
您可以通过使重复非贪婪来解决此问题,使用.*?
. 这将匹配所有的第一个 "
。
所以:
>>> re.findall('\".*?\"', line)
['"1/11/2A"', '"1/20+21/1 1"', '"XX"']
我认为 Martijn Pieters 的答案在概念上可能更清晰;我只提供了这个,因为我认为这可能是你试图解决问题的方式,我想展示你是如何到达那里的。
作为旁注,如果您使用原始字符串,正则表达式代码更容易阅读,因此您可以摆脱多余的反斜杠转义。在这种情况下,反斜杠已经是不必要的了——您不需要在单引号字符串或正则表达式中转义双引号。但是,与其试图记住 Python 解析器需要和不需要转义的内容,以便它可以到达正则表达式解析器,不如只使用原始字符串更容易。所以:
>>> re.findall(r'".*?"', line)
['"1/11/2A"', '"1/20+21/1 1"', '"XX"']