提问者:小点点

重新。芬德尔行为古怪


源字符串为:

# Python 3.4.3
s = r'abc123d, hello 3.1415926, this is my book'

这是我的模式:

pattern = r'-?[0-9]+(\\.[0-9]*)?|-?\\.[0-9]+'

然而,re。搜索可以给我正确的结果:

m = re.search(pattern, s)
print(m)  # output: <_sre.SRE_Match object; span=(3, 6), match='123'>

re。findall只需转储一个空列表:

L = re.findall(pattern, s)
print(L)  # output: ['', '', '']

为什么不能re。findall给我一份预期清单:

['123', '3.1415926']

共3个答案

匿名用户

这里有两件事需要注意:

  • re.findall返回捕获的文本,如果正则表达式模式包含捕获组
  • 模式中的r'\\.'部分匹配两个连续的字符,\和除换行符以外的任何字符。

参见findall参考:

如果模式中存在一个或多个组,则返回组列表;如果模式有多个组,则返回组列表。空匹配将包含在结果中,除非它们触及另一个匹配的开始。

请注意,要使re.findall返回匹配的值,您通常可以

  • 删除冗余捕获组(例如(a(b)c)-

在您的例子中,findall返回了所有捕获的文本,这些文本都是空的,因为您在r'中有\字符串文本试图匹配文本\

要匹配这些数字,您需要使用

-?\d*\.?\d+

正则表达式匹配:

  • --可选减号
  • \d*-可选数字
  • \-可选十进制分隔符
  • \d-1个或多个数字

见演示

以下是IDEONE演示:

import re
s = r'abc123d, hello 3.1415926, this is my book'
pattern = r'-?\d*\.?\d+'
L = re.findall(pattern, s)
print(L)

匿名用户

s = r'abc123d, hello 3.1415926, this is my book'
print re.findall(r'-?[0-9]+(?:\.[0-9]*)?|-?\.[0-9]+',s)

当你使用原始模式时,你不需要逃避两次。

输出:['123',3.1415926']

返回类型也将是字符串列表。如果希望返回类型为整数和浮点数,请使用map

import re,ast
s = r'abc123d, hello 3.1415926, this is my book'
print map(ast.literal_eval,re.findall(r'-?[0-9]+(?:\.[0-9]*)?|-?\.[0-9]+',s))

输出:[123,3.1415926]

匿名用户

只是为了解释为什么你认为search返回了你想要的,而findall没有?

search返回一个SRE_Match对象,该对象包含以下信息:

  • string:属性包含传递给搜索函数的字符串

search在找到第一个马赫数构建SRE_Match对象并返回时停止,请检查此代码:

import re

s = r'abc123d'
pattern = r'-?[0-9]+(\.[0-9]*)?|-?\.[0-9]+'
m = re.search(pattern, s)
print(m.string)  # 'abc123d'
print(m.group(0))  # REGEX matched 123
print(m.groups())  # there is only one group in REGEX (\.[0-9]*) will  empy string tgis why it return (None,) 

s = ', hello 3.1415926, this is my book'
m2 = re.search(pattern, s)  # ', hello 3.1415926, this is my book'
print(m2.string)    # abc123d
print(m2.group(0))  # REGEX matched 3.1415926
print(m2.groups())  # the captured group has captured this part '.1415926'

findall的行为不同,因为它不会在找到第一个mach时停止,直到文本结束,但是如果REGEX包含至少一个捕获组,则findall不会返回匹配的字符串,但捕获组捕获的字符串:

import re
s = r'abc123d , hello 3.1415926, this is my book'
pattern = r'-?[0-9]+(\.[0-9]*)?|-?\.[0-9]+'
m = re.findall(pattern, s)
print(m)  # ['', '.1415926']

当发现第一个马赫数时,第一个元素返回,该马赫数为'123'捕获组仅捕获',但第二个元素在第二次匹配'3.1415926'中捕获,捕获组匹配此零件'.1415926'

如果你想使findall返回匹配的字符串,你应该使所有捕获组()在你的REGEX一个非捕获组(?:)

import re
s = r'abc123d , hello 3.1415926, this is my book'
pattern = r'-?[0-9]+(?:\.[0-9]*)?|-?\.[0-9]+'
m = re.findall(pattern, s)
print(m)  # ['123', '3.1415926']