【问题标题】:In python, how to 'if finditer(...) has no matches'?在 python 中,如何'如果 finditer(...) 没有匹配项'?
【发布时间】:2019-05-08 23:13:57
【问题描述】:

当 finditer() 没有找到任何东西时,我想做点什么。

import re
pattern = "1"
string = "abc"  
matched_iter = re.finditer(pattern, string)
# <if matched_iter is empty (no matched found>.
#   do something.
# else
    for m in matched_iter:
        print m.group()

我能想到的最好办法是手动跟踪找到的:

mi_no_find = re.finditer(r'\w+',"$$%%%%")   # not matching.
found = False
for m in mi_no_find:
    print m.group()
    found = True
if not found:
    print "Nothing found"

不回复的相关帖子:

[编辑]
- 我对枚举或计算总产出没有兴趣。仅当找到 else not found 操作。
- 我知道我可以将 finditer 放入列表中,但这对于大字符串来说效率低下。一个目标是降低内存利用率。

【问题讨论】:

  • 如果它是一个迭代器,你必须遍历它才能知道它是空的。除非正则表达式库增加了一个繁荣,否则你最终不得不做这样的事情,这对我来说足够合理
  • 试试ideone.com/pnI5nq。将可迭代值转换为列表,您可以轻松地将其用于任何进一步的操作。另一种方式:如果if re.search(pattern, s): 则匹配。见ideone.com/tw5jmf
  • 把它变成一个列表:list(re.finditer(pattern, string)) 如果你没有大量的匹配项,你不会注意到性能差异

标签: python regex


【解决方案1】:

2020 年 4 月 10 日更新

使用re.search(pattern, string) 检查是否存在模式。

pattern = "1"
string = "abc"

if re.search(pattern, string) is None:
    print('do this because nothing was found')

返回:

do this because nothing was found

如果您希望遍历返回,请将re.finditer() 放在re.search() 中。

pattern = '[A-Za-z]'
string = "abc"

if re.search(pattern, string) is not None:
    for thing in re.finditer(pattern, string):
        print('Found this thing: ' + thing[0])

返回:

Found this thing: a
Found this thing: b
Found this thing: c

因此,如果您需要这两个选项,请使用带有 if re.search() 条件的 else: 子句。

pattern = "1"
string = "abc"

if re.search(pattern, string) is not None:
    for thing in re.finditer(pattern, string):
        print('Found this thing: ' + thing[0])
else:
    print('do this because nothing was found')

返回:

do this because nothing was found

下面之前的回复(不够,看上面)

如果 .finditer() 与模式不匹配,则不会在相关循环中执行任何命令。

所以:

  • 设置变量在循环之前用于迭代正则表达式返回
  • 在您用于迭代正则表达式返回的循环之后(和之外)调用变量

这样,如果 regex 调用没有返回任何内容,则循环不会执行,并且循环之后的变量调用将返回与它设置的完全相同的变量。

下面,示例 1 演示了查找模式的正则表达式。示例 2 显示正则表达式未找到模式,因此循环内的变量永远不会设置。 示例 3 显示了我的建议 - 在正则表达式循环之前设置变量的位置,因此如果正则表达式未找到匹配项(并且随后不会触发循环),循环后的变量调用返回初始变量集(确认未找到正则表达式模式)。

记得导入 import re 模块。

示例 1(在字符串 'hello world' 中搜索字符 'he' 将返回 'he')

my_string = 'hello world'
pat = '(he)'
regex = re.finditer(pat,my_string)

for a in regex:
    b = str(a.groups()[0])
print(b)

# returns 'he'

示例 2(在字符串 'hello world' 中搜索字符 'ab' 不匹配任何内容,因此 'for a in regex:' 循环不会执行并且不会为 b 变量分配任何值。)

my_string = 'hello world'
pat = '(ab)'
regex = re.finditer(pat,my_string)

for a in regex:
    b = str(a.groups()[0])
print(b)

# no return

示例 3(再次搜索字符 'ab',但这次在循环之前将变量 b 设置为 'CAKE',并在之后调用变量 b,在循环外返回初始变量 - 即 'CAKE' - 因为循环没有执行)。

my_string = 'hello world'
pat = '(ab)'
regex = re.finditer(pat,my_string)

b = 'CAKE' # sets the variable prior to the for loop
for a in regex:
    b = str(a.groups()[0])
print(b) # calls the variable after (and outside) the loop

# returns 'CAKE'

还值得注意的是,在设计您的模式以输入正则表达式时,请确保使用括号来指示组的开始和结束。

pattern = '(ab)' # use this
pattern = 'ab' # avoid using this

回到最初的问题:

由于没有找到不会执行 for 循环(正则表达式中的 for a),用户可以预加载变量,然后在 for 循环之后检查原始加载值。这将允许用户知道是否没有找到任何东西。

my_string = 'hello world'
pat = '(ab)'
regex = re.finditer(pat,my_string)

b = 'CAKE' # sets the variable prior to the for loop
for a in regex:
    b = str(a.groups()[0])
if b == ‘CAKE’:
    # action taken if nothing is returned

【讨论】:

  • 我觉得这有点没抓住重点。问题是如何处理“如果没有找到”的情况。
  • @Leo Ufimtsev 这很公平。当 .finditer() 没有找到任何东西时,它会绕过 for 循环中的后续条件代码(因为没有,'for a in...)。当用户预加载变量时,它在“for循环”期间永远不会被替换。因此,在循环之后,用户可以检查变量的预加载值以测试是否没有发生任何事情。我需要补充我的答案!
  • @LeoUfimtsev 查看我的更新,使用 re.search() 和“is None”或“is not None”来构建更好的建议。让我知道这是否有帮助!
  • 我很佩服你的坚持。我认为这应该得到奖励。这确实是一个很好的解决方案。标记为已接受的答案。谢谢您的意见。
【解决方案2】:

如果性能不是问题,只需使用findalllist(finditer(...)),它们会返回一个列表。

否则,您可以使用next“窥视”生成器,然后在引发StopIteration 时正常循环。虽然还有其他方法可以做到,但这对我来说是最简单的:

import itertools
import re

pattern = "1"
string = "abc"  
matched_iter = re.finditer(pattern, string)

try:
    first_match = next(matched_iter)
except StopIteration:
    print("No match!") # action for no match
else:
    for m in itertools.chain([first_match], matched_iter):
        print(m.group())

【讨论】:

    【解决方案3】:

    您可以使用next 探测迭代器,然后将结果返回到一起chain,而StopIteration 除外,这意味着迭代器是空的:

    import itertools as it
    
    matches = iter([])
    try:
        probe = next(matches)
    except StopIteration:
        print('empty')
    else:
        for m in it.chain([probe], matches):
            print(m)
    

    关于您的解决方案,您可以直接检查m,预先将其设置为None

    matches = iter([])
    m = None
    for m in matches:
        print(m)
    if m is None:
        print('empty')
    

    【讨论】:

    • 只将next 调用放在try 中会更安全,而将其余的快乐路径放在else 中。
    • 我喜欢 m = None hack。这很简单,我可以在一次采访中记住这一点。乍一看,try/catch 有点难以理解。
    【解决方案4】:

    如果字符串中没有匹配项,它会打印原始字符串。 它将替换字符串的位置n

    更多参考:https://docs.python.org/2/howto/regex.html

    
    
    Input_Str = "FOOTBALL"
    
    def replacing(Input_String, char_2_replace, replaced_char, n):
        pattern = re.compile(char_2_replace)
        if len(re.findall(pattern, Input_String)) >= n: 
            where = [m for m in pattern.finditer(Input_String)][n-1]
            before = Input_String[:where.start()]
            after = Input_String[where.end():]
            newString = before + replaced_char + after
        else: 
            newString = Input_String
        return newString
    
    print(replacing(Input_Str, 'L', 'X', 4))```
    

    【讨论】:

      【解决方案5】:

      我知道这个答案来晚了,但是非常适合 Python 3.8+

      您可以使用新的warlus operator := 运算符和next(iterator[, default]) 来解决re.finditer(pattern, string, flags=0) 中的“不匹配”问题,如下所示:

      import re
      
      pattern_ = "1"
      string_ = "abc" 
      
      def is_match():
          was_found = False
          while next((match := re.finditer(pattern_, string_)), None) is not None:
              was_found = True
              yield match.group()  # or just print it
          return was_found
      
      

      【讨论】:

        猜你喜欢
        • 2017-08-09
        • 2015-06-08
        • 2011-04-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-05
        • 2010-12-04
        相关资源
        最近更新 更多