Python re.findall表现得很奇怪

O'S*_*ker 18 python regex

源字符串是:

# Python 3.4.3
s = r'abc123d, hello 3.1415926, this is my book'
Run Code Online (Sandbox Code Playgroud)

这是我的模式:

pattern = r'-?[0-9]+(\\.[0-9]*)?|-?\\.[0-9]+'
Run Code Online (Sandbox Code Playgroud)

但是,re.search可以给我正确的结果:

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

re.findall 只是转出一个空列表:

L = re.findall(pattern, s)
print(L)  # output: ['', '', '']
Run Code Online (Sandbox Code Playgroud)

为什么不能re.findall给我预期的清单:

['123', '3.1415926']
Run Code Online (Sandbox Code Playgroud)

Wik*_*żew 17

这里有两点需要注意:

  • 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+
Run Code Online (Sandbox Code Playgroud)

正则表达式匹配:

  • -? - 可选的减号
  • \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)
Run Code Online (Sandbox Code Playgroud)


vks*_*vks 8

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

escape当你使用时,你不需要两次raw mode.

输出:['123', '3.1415926']

返回类型也是一个列表.strings如果你想要返回类型integersfloats使用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))
Run Code Online (Sandbox Code Playgroud)

输出: [123, 3.1415926]

  • 虽然这个正则表达式效率低于我的,但我承认`ast'的技巧很酷(尽管OP中没有要求). (2认同)
  • @ O'Skywalker就像天才一样:P ..........只是练习.......你很快就会成为一名警察!!!!!!!! (2认同)
  • 您还可以使用像这样的第一个字符区分来减少步骤:`(?=[-\d.])-?(?:\d+(?:\.\d*)?|\.\d+)` (2认同)