[英]re.findall behaves weird
源字符串是:
# Python 3.4.3
s = r'abc123d, hello 3.1415926, this is my book'
这是我的模式:
pattern = r'-?[0-9]+(\\.[0-9]*)?|-?\\.[0-9]+'
然而, re.search
可以给我正确的结果:
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']
这里有两点需要注意:
re.findall
返回捕获的文本r'\\.'
模式中的部分匹配两个连续的字符, \
和除换行符以外的任何字符。 请参阅findall
参考:
如果模式中存在一个或多个组,则返回组列表; 如果模式有多个组,这将是一个元组列表。 空匹配包含在结果中,除非它们触及另一个匹配的开始。
请注意,要使re.findall
只返回匹配值,您通常可以
(a(b)c)
-> abc
)(
替换为(?:
) ,除非存在引用模式中组值的反向引用(然后见下文)re.finditer
( [x.group() for x in re.finditer(pattern, s)]
) 在您的情况下, 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)
使用raw 模式时不需要转义两次。
输出: ['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
没有?
搜索返回一个SRE_Match
对象,其中包含一些信息,例如:
string
:属性包含传递给搜索函数的字符串。re
: 搜索功能中使用的REGEX
对象。groups()
:由REGEX
中的捕获组捕获的字符串列表。group(index)
:使用index > 0
按组检索捕获的字符串。group(0)
:返回由REGEX
匹配的字符串。 当它找到第一个马赫构建SRE_Match
对象并返回它时, search
停止,检查以下代码:
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']
当找到第一个马赫时,第一个element
返回'123'
捕获组仅捕获''
,但第二个element
在第二个匹配中捕获'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']
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.