0

我有一些字符串包含两个引号之间的信息,例如:

cc "1/11/2A" "1/20+21/1 1" "XX" 0

re.findall('\"*\"', line)用来匹配引号之间的部分,但由于某种原因不起作用。我尝试了很多其他的东西,但我得到的只是一些空列表,里面什么都没有。我究竟做错了什么 ?

4

3 回答 3

4

您正在匹配 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']

[^...]否定字符类表示法意味着:匹配任何包含在此处命名的字符集中的字符。[^"]因此匹配任何不是引号的字符,将匹配的字符巧妙地限制为引号的所有字符。

于 2013-02-08T11:47:54.120 回答
2

应该是r'"[^"]*"'。您的模式匹配一"​​行中的一个或多个字符。

In [4]: re.findall(r'"[^"]*"', line)
Out[4]: ['"1/11/2A"', '"1/20+21/1 1"', '"XX"']
于 2013-02-08T11:47:24.187 回答
2

看起来您希望*匹配“任何内容”,就像它在文件名通配符中所做的那样。

但这不是它在正则表达式中的含义。它修改前面的表达式,以匹配该表达式的零个或多个副本。

要获取文件名样式的通配符,您需要使用.*.

然而,这实际上不起作用,因为.匹配任何东西——包括". 所以,它会抓取最后一个"字符的所有内容,只留下表达式的其余部分,意思是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"']
于 2013-02-08T11:56:41.610 回答