在re.search中返回NoneType与返回

1 投票
4 回答
913 浏览
提问于 2025-04-18 14:04

我查了一下,没找到这个具体的问题,不过如果是重复的请告诉我。

我写了一个叫做 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') 
''

撰写回答