正则表达式不返回结果

Posted

技术标签:

【中文标题】正则表达式不返回结果【英文标题】:Regex returns no results 【发布时间】:2017-11-22 14:10:34 【问题描述】:

我编写了一个正则表达式,可以从 unicode 字符串中提取年份(例如,2014-2015)。正则表达式中的\d1,2\^ 代表月份代码,可能存在也可能不存在。

不管怎样,这是我写的代码:

# -*- coding: utf-8 -*-

import re
list_elem = '''Frank P. Smith (1886–1888)
Edgar Grant Sisson (1914–1917)
Douglas Z. Doty (1917–1918)
 Ray Long (1918–1931)

Harry Payne Burton (1931–1942)
Frances Whiting (1942–1945)
Arthur Gordon (1946–1948)'''

period_regex = ur'(\d1,2\^)?\s?\d4\s?(–|-)\s?(\d1,2\^)?\s?\d4'  #regex for checking if its a single year or period

#checking if a normal regex works
print re.search(r'W', list_elem, flags=re.IGNORECASE)
print re.findall(r'W\w+', list_elem, flags=re.IGNORECASE)

#main regex
print re.search(period_regex, list_elem, flags=re.IGNORECASE)
print re.findall(period_regex, list_elem, flags=re.IGNORECASE)

输出是:

<_sre.SRE_Match object at 0x7f8bfd1b5510>
['Whiting']
None
[]

我编写的正则表达式似乎工作正常。这是正则表达式的链接:https://regex101.com/r/scAtgw/2

但是,当我运行我的程序时,我仍然得到一个空匹配。任何想法我做错了什么??

【问题讨论】:

可能与Unicode有关。在这里,it works。顺便说一句,如果您只需要获得所有匹配项,我认为您需要将所有捕获组替换为非捕获组。喜欢r'(?:\d1,2\^)?\s?\d4\s?[–-]\s?(?:\d1,2\^)?\s?\d4' @WiktorStribiżew 是的,这是一个更好的正则表达式,可以满足我的要求,但我仍然无法在我的机器上找到任何匹配项。任何想法如何解决与 unicode 相关的问题? 您需要通过在其声明中添加u"" 前缀来使list_elem 成为Unicode 字符串。见ideone.com/0d4nqv。 @WiktorStribiżew 我这样做了,仍然没有结果:( 看,它在这里工作 - ideone.com/Ltw4rA。 【参考方案1】:

这里的主要问题是,由于您使用的是 Unicode 文本,因此输入字符串也应该是 Unicode。这可以通过在字符串文字中添加 u 前缀来解决。

但是,re.findall 将存在一个问题,即仅返回在模式中定义的捕获组内容。由于您的模式包含捕获组,因此您将获得一个元组列表。因此,您需要将所有捕获组转换为非捕获组。

如果您需要打印这些值,您可能需要.encode("utf8") 这些值。

见Python 2 demo online:

# -*- coding: utf-8 -*-
import re
list_elem = u'''Frank P. Smith (1886–1888)
    Edgar Grant Sisson (1914–1917)
    Douglas Z. Doty (1917–1918)
     Ray Long (1918–1931)

    Harry Payne Burton (1931–1942)
    Frances Whiting (1942–1945)
    Arthur Gordon (1946–1948)'''

period_regex = ur'(?:\d1,2\^)?\s?\d4\s?[–-]\s?(?:\d1,2\^)?\s?\d4'  #regex for checking if its a single year or period
print re.search(r'W', list_elem, flags=re.IGNORECASE)
print re.findall(r'W\w+', list_elem, flags=re.IGNORECASE)

print re.search(period_regex, list_elem, flags=re.IGNORECASE).group(0).encode('utf8')
for x in  re.findall(period_regex, list_elem, flags=re.IGNORECASE):
    print x.encode('utf8')

结果:

<_sre.SRE_Match object at 0x2b05baf525e0>
[u'Whiting']
1886–1888
1886–1888
1914–1917
1917–1918
1918–1931
1931–1942
1942–1945
1946–1948

注意list_elem = u'''Frank 中的u""" 和所有( 在模式中都替换为(?:,使组不被捕获。

此外,[–-](?:–|-) 相同,但更短且更高效。

【讨论】:

这正是我正在寻找的答案。也感谢您改进正则表达式:)【参考方案2】:

在打印语句中的list_elem.encode('utf8') 中添加'u' 作为前缀应该可以解决您的问题。例如,

print re.search(period_regex, list_elem, flags=re.IGNORECASE).group(0).encode('utf8')

【讨论】:

以上是关于正则表达式不返回结果的主要内容,如果未能解决你的问题,请参考以下文章

Grep 不匹配正则表达式

根据返回的结果和前一个正则表达式的规则创建一个新的正则表达式 |索引正则表达式并查看正则表达式如何匹配子字符串

JS正则表达式之--?:

js密码正则表达式:要求包含大小写字母、数字和特殊符号,8~16位

js密码正则表达式:要求包含大小写字母、数字和特殊符号,8~16位

Javascript split() 正则表达式在 Chrome 中返回不需要的逗号