Python 如果列表中的任何字符串匹配正则表达式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37974047/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 20:11:25  来源:igfitidea点击:

If any strings in a list match regex

pythonregex

提问by ewok

I need to check if any of the strings in a list match a regex. If any do, I want to continue. The way I've always done it in the past is using list comprehension with something like:

我需要检查列表中的任何字符串是否与正则表达式匹配。如果有的话,我想继续。我过去一直这样做的方式是使用列表理解,例如:

r = re.compile('.*search.*')
if [line for line in output if r.match(line)]:
  do_stuff()

Which I now realize is pretty inefficient. If the very first item in the list matches, we can skip all the rest of the comparisons and move on. I could improve this with:

我现在意识到这是非常低效的。如果列表中的第一项匹配,我们可以跳过所有其余的比较并继续。我可以通过以下方式改进:

r = re.compile('.*search.*')
for line in output:
  if r.match(line):
    do_stuff()
    break

But I'm wondering if there's a more pythonic way to do this.

但我想知道是否有更 Pythonic 的方式来做到这一点。

回答by MrAlexBailey

You can use the builtin any():

您可以使用内置any()

if any(re.match(line) for line in output):
    do_stuff()

Passing in the lazy generator to any()will allow it to exit on the first match without having to check any farther into the iterable.

any()传入惰性生成器 to将允许它在第一次匹配时退出,而无需进一步检查可迭代对象。

回答by Xavier Guihot

Starting Python 3.8, and the introduction of assignment expressions (PEP 572)(:=operator), we can also capture a witnessof an anyexpression when a match is found and directly use it:

开始Python 3.8,并引进赋值表达式(PEP 572) :=运营商),我们也可以捕捉一个证人的的any表达时,发现匹配,并直接使用它:

# 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'

For each item, this:

对于每个项目,这是:

  • Applies the regex search (pattern.match(x))
  • Assigns the result to a matchvariable (either Noneor a re.Matchobject)
  • Applies the truth value of matchas part of the any expression (None-> False, Match-> True)
  • If matchis None, then the anysearch loop continues
  • If matchhas captured a group, then we exit the anyexpression which is considered Trueand the matchvariable can be used within the condition's body
  • 应用正则表达式搜索 ( pattern.match(x))
  • 将结果分配给match变量(Nonere.Match对象)
  • 应用 的真值match作为 any 表达式的一部分 ( None-> False, Match-> True)
  • 如果matchNone,则any搜索循环继续
  • 如果match已经捕获了一个组,那么我们退出any被考虑的表达式True并且match变量可以在条件的主体中使用

回答by I. Jovanov

Given that I am not allowed to comment yet, I wanted to provide a small correction to MrAlexBailey's answer, and also answer nat5142's question. Correct form would be:

鉴于我还不能发表评论,我想对 MrAlexBailey 的回答做一个小的更正,并回答 nat5142 的问题。正确的形式是:

r = re.compile('.*search.*')
if any(r.match(line) for line in output):
    do_stuff()

If you desire to find the matched string, you would do:

如果你想找到匹配的字符串,你可以这样做:

lines_to_log = [line for line in output if r.match(line)]

In addition, if you want to find all lines that match any compiled regular expression in a list of compiled regular expressions r=[r1,r2,...,rn], you can use:

此外,如果要在已编译正则表达式列表 r=[r1,r2,...,rn] 中查找与任何已编译正则表达式匹配的所有行,可以使用:

lines_to_log = [line for line in output if any(reg_ex.match(line) for reg_ex in r)]

回答by tinnick

In reply to a question asked by @nat5142, in the answer given by @MrAlexBailey: "Any way to access the matched string using this method? I'd like to print it for logging purposes", assuming "this" implies to:

回答@nat5142 提出的问题,在@MrAlexBailey 给出的答案中: “使用此方法访问匹配字符串的任何方式?我想打印它以进行日志记录”,假设“这个”意味着:

if any(re.match(line) for line in output):
    do_stuff()

You can do a for loop over the generator

您可以对生成器执行 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

Another approach is mapping each match with the map function:

另一种方法是使用 map 函数映射每个匹配项:

# r = re.compile('.*search.*')
# log = lambda x: print(x)
map(log, [line for line in output if r.match(line)])

Although this does not involve the "any" function and might not even be close to what you desire...

虽然这不涉及“任何”功能,甚至可能不接近您想要的......

I thought this answer was not very relevant so here's my second attempt... I suppose you could do this:

我认为这个答案不是很相关,所以这是我的第二次尝试......我想你可以这样做:

# def log_match(match):
#    if match: print(match)
#    return match  
if any(log_match(re.match(line)) for line in output):
    do_stuff()