Python findall不返回预期值

时间:2013-02-08 11:45:13

标签: python regex

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

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

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

3 个答案:

答案 0 :(得分: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']

[^...]否定字符类符号表示:匹配此处命名的字符集中包含的任何字符。 [^"]因此匹配任何非引号的字符,将匹配的字符整齐地限制在 引号内的所有内容。

答案 1 :(得分:2)

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

In [4]: re.findall(r'"[^"]*"', line)
Out[4]: ['"1/11/2A"', '"1/20+21/1 1"', '"XX"']

答案 2 :(得分: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"']