【问题标题】:does Regex omit part of a string if it has already been matched?如果已经匹配,Regex 是否会省略字符串的一部分?
【发布时间】:2020-10-26 19:59:13
【问题描述】:

Python 3.8.2 手头的任务很简单:匹配由单个下划线分隔的小写字符。所以模式可能是r"[a-z]+_[a-z]+"

现在我的问题是我希望 re.findall() 将以下所有内容配对:

“ash_tonic_transit_so_kern_err_looo_”

我没有将每个下划线周围的所有单词('ash_tonic'、'tonic_transit'、'transit_so'、ETC)都删掉,而是得到三对:['ash_tonic'、'transit_so'、'kern_err']

一旦找到匹配项,python 是否会重新省略部分字符串,而不是再次运行搜索?

import re
def match_lower(s):
    patternRegex = re.compile(r'[a-z]+_[a-z]+')
    mo =  patternRegex.findall(s)
    return mo



print(match_lower('ash_tonic_transit_so_kern_err_looo_'))

【问题讨论】:

  • 重新模块不会进行部分重新匹配,一旦你匹配了字符串之外的东西。
  • 这就是 all 正则表达式风格的工作方式 - 您已经指定(简化)[a-z]_[a-z] 所以从 a_b_c_d 它将匹配 a_b,一旦使用,正则表达式将继续那里。
  • 您可以在前瞻 (?=(?<![a-z])([a-z]+_[a-z]+)) regex101.com/r/VW7BKW/1 内使用带有负后瞻的捕获组
  • @Thefourthbird 有趣的是,我从没想过lookbehinds/lookaheads可以嵌套。直到。

标签: python regex python-re


【解决方案1】:

您可以使用带有捕获组的正向前瞻来获取匹配项,并开始匹配,使用否定的后向查看断言直接在左侧的不是 char a-z。

使用re.findall 将返回捕获组中的值。

(?<![a-z])(?=([a-z]+_[a-z]+))

说明

  • (?&lt;![a-z]) 负向后视,断言左边的不是字符 a-z
  • (?= 正向前瞻,断言右边是什么
    • ([a-z]+_[a-z]+) 捕获组 1,匹配 1+ chars a-z _ 1+ chars a-z
  • ) 关闭前瞻

Regex demo | Python demo

import re
 
regex = r"(?<![a-z])(?=([a-z]+_[a-z]+))"     
test_str = "ash_tonic_transit_so_kern_err_looo_"     
print(re.findall(regex, test_str))

输出

['ash_tonic', 'tonic_transit', 'transit_so', 'so_kern', 'kern_err', 'err_looo']

【讨论】:

  • 谢谢!我看到这个解决方案就像我想要的那样工作,我还没有学习正则表达式的环视位,但我会使用你的解决方案作为指导
【解决方案2】:

the documentation of re.findall 中明确提到了这一点:

返回字符串中所有不重叠匹配的模式,作为字符串列表。

例如,'ash_tonic''tonic_transit' 重叠,因此它们不会被视为两个不同的匹配项。

【讨论】:

  • 我明白了,有什么解决办法吗?我没有看到任何可能的 re.findall() 标志来修改此行为
  • @veziop,好吧,the lookahed/lookbehind solution 看起来不错
猜你喜欢
  • 2012-10-29
  • 2014-07-17
  • 1970-01-01
  • 2013-06-04
  • 2021-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多