我需要检查列表中的任何字符串是否与正则表达式匹配。如果有的话,我想继续。我过去总是这样做的方式是使用列表理解,例如:
r = re.compile('.*search.*')
if [line for line in output if r.match(line)]:
do_stuff()
我现在意识到这是非常低效的。如果列表中的第一个项目匹配,我们可以跳过所有其余的比较并继续。我可以通过以下方式改进:
r = re.compile('.*search.*')
for line in output:
if r.match(line):
do_stuff()
break
但我想知道是否有更多的pythonic方式来做到这一点。
答案 0 :(得分:16)
您可以使用内置any()
:
if any(re.match(line) for line in output):
do_stuff()
将延迟生成器传递给any()
将允许它在第一个匹配时退出,而不必再检查迭代中的任何一个。
答案 1 :(得分:1)
鉴于尚未允许我发表评论,我想对AlexBailey先生的回答做一个小小的更正,并回答nat5142的问题。正确的格式为:
r = re.compile('.*search.*')
if any(r.match(line) for line in output):
do_stuff()
如果您希望找到匹配的字符串,请执行以下操作:
lines_to_log = [line for line in output if r.match(line)]
此外,如果要在已编译正则表达式列表r = [r1,r2,...,rn]中查找与任何已编译正则表达式匹配的所有行,则可以使用:
lines_to_log = [line for line in output if any(reg_ex.match(line) for reg_ex in r)]
答案 2 :(得分:1)
从Python 3.8
开始并引入assignment expressions (PEP 572)(:=
运算符),我们还可以在以下情况下捕获any
表达式的 witness 找到一个匹配项并直接使用它:
# pattern = re.compile('.*search.*')
# items = ['hello', 'searched', 'world', 'still', 'searching']
if any((match := pattern.match(x)) for x in items):
print(match.group(0))
# 'searched'
对于每个项目,此:
pattern.match(x)
)match
变量(None
或re.Match
对象)match
的真值用作任何表达式的一部分(None
-> False
,Match
-> True
)match
是None
,则any
搜索循环继续match
捕获了一个组,则我们退出被认为是any
的{{1}}表达式,并且True
变量可以在条件体内使用答案 3 :(得分:1)
在@MrAlexBailey给出的答案中,回复@ nat5142提出的问题: “使用此方法访问匹配的字符串的任何方式吗?我想出于记录目的将其打印出来” ,假设“ this”表示:
if any(re.match(line) for line in output):
do_stuff()
您可以在生成器上进行for循环
# r = re.compile('.*search.*')
for match in [line for line in output if r.match(line)]:
do_stuff(match) # <- using the matched object here
另一种方法是使用map函数映射每个匹配项:
# r = re.compile('.*search.*')
# log = lambda x: print(x)
map(log, [line for line in output if r.match(line)])
尽管它不涉及“任何”功能,甚至可能与您想要的功能不符...
我认为这个答案不是很相关,所以这是我的第二次尝试。 我想你可以这样做:
# def log_match(match):
# if match: print(match)
# return match
if any(log_match(re.match(line)) for line in output):
do_stuff()