有一种已知的"模式"获取捕获的组值,如果不匹配则获取空字符串:
match = re.search('regex', 'text')
if match:
value = match.group(1)
else:
value = ""
或:
match = re.search('regex', 'text')
value = match.group(1) if match else ''
有一种简单的pythonic方法可以在一行中完成吗?
换句话说,如果没有找到捕获组,我可以提供默认值吗?
例如,我需要从_
字符串后面的文本中提取所有字母数字字符(和key=
):
>>> import re
>>> PATTERN = re.compile('key=(\w+)')
>>> def find_text(text):
... match = PATTERN.search(text)
... return match.group(1) if match else ''
...
>>> find_text('foo=bar,key=value,beer=pub')
'value'
>>> find_text('no match here')
''
find_text()
是否可以成为一个班轮?
这只是一个例子,我正在寻找一种通用方法。
答案 0 :(得分:10)
匹配对象的布尔值始终为
True
。由于match()
和search()
在没有匹配项时返回None
,您可以测试是否与简单的if语句匹配:match = re.search(pattern, string) if match: process(match)
由于没有其他选项,并且当您使用某个功能时,我想提供此替代选项
def find_text(text, matches = lambda x: x.group(1) if x else ''):
return matches(PATTERN.search(text))
assert find_text('foo=bar,key=value,beer=pub') == 'value'
assert find_text('no match here') == ''
这是完全相同的,但只有你需要做的检查是默认参数化的。
在评论中考虑@ Kevin的解决方案和@ devnull的建议,你可以做这样的事情
def find_text(text):
return next((item.group(1) for item in PATTERN.finditer(text)), "")
这利用了以下事实:next
接受默认值作为参数返回。但这有在每次迭代时创建生成器表达式的开销。所以,我会坚持第一个版本。
答案 1 :(得分:4)
您可以使用模式,使用捕获组中字符串末尾的空替代项:
>>> re.search(r'((?<=key=)\w+|$)', 'foo=bar,key=value').group(1)
'value'
>>> re.search(r'((?<=key=)\w+|$)', 'no match here').group(1)
''
答案 2 :(得分:3)
可以在单个单行中引用函数调用的结果两次:创建一个lambda表达式并在参数中调用该函数。
value = (lambda match: match.group(1) if match else '')(re.search(regex,text))
但是,我并不认为这特别易读。负责任地编码 - 如果您要撰写棘手的代码,请留下描述性评论!
答案 3 :(得分:3)
Re:&#34;有一种简单的pythonic方法可以在一行中完成吗?&#34;答案是否。任何让它在一行中工作的方法(没有定义你自己的包装器),阅读比你已经提出的方式更难听。但是定义自己的包装 完全是Pythonic,就像使用两条非常易读的行而不是一条难以阅读的行。
答案 4 :(得分:2)
单行版本:
if re.findall(pattern,string): pass
这里的问题是你想要准备多场比赛或确保你的模式只打一次。扩展版本:
# matches is a list
matches = re.findall(pattern,string)
# condition on the list fails when list is empty
if matches:
pass
因此,对于您的示例,“在key = string”之后从文本中提取所有字母数字字符(和_):
# Returns
def find_text(text):
return re.findall("(?<=key=)[a-zA-Z0-9_]*",text)[0]
答案 5 :(得分:2)
一个衬垫,一个衬垫......为什么你不能在2行上写它?
getattr(re.search('regex', 'text'), 'group', lambda x: '')(1)
你的第二个解决方案,如果罚款。如果您愿意,可以从中创建一个功能。我的解决方案是出于演示目的,它绝不是pythonic。
答案 6 :(得分:2)
一条线,虽然不是Pythonic。
find_text = lambda text: (lambda m: m and m.group(1) or '')(PATTERN.search(text))
实际上,在Scheme编程语言中,所有局部变量构造都可以从lambda函数应用程序派生。
答案 7 :(得分:1)
你可以这样做:
value = re.search('regex', 'text').group(1) if re.search('regex', 'text') else ''
考虑到你运行正则表达式两次这一事实,它并不是非常有效。
或者@Kevin建议只运行一次:
value = (lambda match: match.group(1) if match else '')(re.search(regex,text))
答案 8 :(得分:1)
从Python 3.8
开始并引入assignment expressions (PEP 572)(:=
运算符),我们可以命名正则表达式搜索表达式pattern.search(text)
,以便同时检查是否存在匹配项(因为pattern.search(text)
返回None
或re.Match
对象)并使用它来提取匹配的组:
# pattern = re.compile(r'key=(\w+)')
match.group(1) if (match := pattern.search('foo=bar,key=value,beer=pub')) else ''
# 'value'
match.group(1) if (match := pattern.search('no match here')) else ''
# ''