在re.search中返回NoneType与返回
我查了一下,没找到这个具体的问题,不过如果是重复的请告诉我。
我写了一个叫做 find_results 的函数,它会在一个字符串中查找分隔符,然后返回分隔符和换行符之间的内容:
def find_results(findme, separator, string):
linelist=string.split('\n')
for line in linelist:
if re.search(findme, line):
#Split based on the separator we were sent, but only on the first occurrance
line = line.split(separator, 1)
return line[1].strip()
#End if line.find
#end for loop
return ""
#end find_results
这个函数运行得很好,但我觉得应该有更符合 Python 风格的方法来完成同样的任务,老实说,调用一个自定义函数来处理这么简单的事情让我觉得有点傻。
我最近学会了在正则表达式中使用集合,所以在某些情况下我可以用 re.search 来替代这个函数。如果分隔符是冒号的话,比如:
re.search("Preceeding\ Text:(.*)$", string).group(1)
但这样做的问题是,当没有结果时,我会遇到 "NoneType" 崩溃,因为 "NoneType" 没有 "group" 这个属性。我可以用 if 语句或者 try/except 语句来检查结果,但这样就失去了从 find_results 切换过来的意义。
我想问的问题是:
- 有没有办法避免 NoneType 崩溃,直接返回 ""(空字符串)?
- 有没有其他一种一行代码就能完成这个的方式?
- 如果我必须使用自定义函数,有没有更符合 Python 风格(而且不那么尴尬)的方法来写它?
4 个回答
0
re.findall 是一个很棒的工具,可以用来查找多个相同模式的实例:
r = re.compile("^[^:]*:(.*)$", re.MULTILINE)
r.findall("a: b\nc: d")
0
这里有一行你想要的代码。函数式编程真的很棒。
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import re
if __name__ == '__main__':
findme= 'abc'
sep = ','
stringa = '1,2,3,4,5,abc'
print map(lambda line, findme=findme, sep=sep: line.split(sep, 1)[1].strip() if re.search(findme, line) else "", stringa.split('\n'))
1
你想要的那行代码是:
return re.findall(r'Preceeding\ Text:(.*)$', text) or ''
如果没有找到任何匹配的内容,findall()
会返回一个空列表。在这种情况下,你希望结果是 ''
,这就是使用 or 的原因。
不要把 string
当作变量名,因为它和内置的字符串模块有冲突。
1
可以使用 str.partition 这个方法:
def find_results(findme, separator, s):
tgt=s[s.find(findme):]
return tgt.partition(separator)[2]
>>> find_results('Text', ':', 'Preceding Text:the rest')
'the rest'
>>> find_results('Text', ';', 'Preceding Text:the rest')
''
>>> find_results('text', ':', 'Preceding Text:the rest')
''
因为 partition 方法总是返回一个包含三个元素的元组,如果找不到内容,最后一个元素会是 ''
(空字符串),所以这可能就是你想要的一行代码:
>>> s='Preceding Text:the rest'
>>> s[s.find('Text'):].partition(':')[2]
'the rest'
>>> s[s.find('Text'):].partition(';')[2]
''
如果你要查找的部分 findme
或者分隔符 separator
只有在使用正则表达式时才有用,可以用 re.split 方法,并加上 try/except 来处理可能出现的错误:
def find_re_results(findme, separator, s):
p1=re.compile(findme)
p2=re.compile(separator)
m=p1.search(s)
if m:
li=p2.split(s[m.start():], maxsplit=1)
else:
return ''
try:
return li[1]
except IndexError:
return ''
示例:
>>> find_re_results('\d+', '\t', 'Preceding 123:;[]\\:the rest')
''
>>> find_re_results('\d+', '\W+', 'Preceding 123:;[]\\:the rest')
'the rest'
>>> find_re_results('\t', '\W+', 'Preceding 123:;[]\\:the rest')
''