【问题标题】:regular expression to match a digit present n or more times before character and n or less times after it正则表达式匹配在字符之前出现 n 次或更多次且在其后出现 n 次或更少次的数字
【发布时间】:2020-01-11 00:08:30
【问题描述】:

我需要一个正则表达式来使用 Python 根据两个条件匹配一个字符串:

  1. 一个数字在, 之前出现至少 n
  2. 从条件 1 匹配的数字在 , 之后最多出现 m

注意:只有一个逗号。

例如:

111,222 n = 3m = 0 应该返回 true,因为 1 在 , 之前出现 3 次或更多次并且在,之后0次

111,212n = 3m = 0 应该返回 false,因为尽管 1 在 @987654329 之前存在 3 次或更多次 @它在,之后出现超过0

111,212n = 3m = 1 应该返回 true,因为 1 在 , 之前出现 3 次或更多次并且在,之后只有1次

我使用(\d+)\1{n,} 来捕获数字并检查第一个条件。但是我在第二种情况下遇到了麻烦。我试过(\d+)\1{n,},\d*((?!\1)){0,m}\d*,但它不起作用。

我假设正则表达式中, 之后的\d 与不应该出现的捕获组匹配,知道吗?

【问题讨论】:

  • 您的规则暗示了\d{n,},\d{0,m} 模式。但它不适用于提供的字符串,所以问题不清楚。
  • (\d)(?:(?:(?!\1)\d)*\1){2}\d*?,(?:(?!\1)\d)*(?:\1(?:(?!\1)\d)*){1}$ 其中{2}n-1{1}m 如看到here
  • @WiktorStribiżew 它需要澄清,但我几乎可以肯定它们在两个部分中表示相同的数字 - 所以1 在第一部分出现 3 次,在第二部分出现 0 次(对于第一种情况)。其余情况相同,但输入不同。至少,这是我从用户发布的第二个正则表达式中收集到的。
  • @ctwheels 是的!我刚刚编辑了这个问题。抱歉,不清楚。
  • 您使用什么语言/工具?来自regex tag info:“由于正则表达式尚未完全标准化,所有带有此标签的问题还应包含一个指定适用的编程语言或工具的标签。”

标签: python regex


【解决方案1】:

代码

您最好在不使用正则表达式的代码中执行此操作,方法是拆分,,然后计算一个数字在两个部分中出现的次数。在 python 中,它会是这样的:

See code in use here - 更改nm 的值

ss = ['111,222','111,212']
n,m = 3,1
for s in ss:
    x,y = s.split(',')
    for c in x:
        if (x.count(c) >= n) and (y.count(c) <= m):
            print(s)
            break

正则表达式

在正则表达式中,它可以通过以下方式完成,但它确实不理想:

See regex in use here

(\d)(?:(?:(?!\1)\d)*\1){2}\d*,(?:(?!\1)\d)*(?:\1(?:(?!\1)\d)*){0,1}$
#                       ^ n-1                                    ^ m

既然你只关心它是否满足n的最低要求,我们不需要做{2,}

【讨论】:

    【解决方案2】:

    在模式(\d+)\1{n,} 的这一部分中,如果 n=3,您将重复您已经捕获的内容 3 次,因此它将尝试匹配 4 位而不是 3 位。

    我建议不要使用{0,m},而是匹配{1}{2} 等的确切时间,并且在将反向引用与第1 组匹配后,使用否定前瞻断言不会再出现任何事件。

    ^(\d)\1{2,},(?=((?:\d*?\1){1}))\2(?!\d*\1)\d*
    
    • ^ 字符串开始
    • (\d)\1{2,}, 捕获第 1 组,匹配一个数字并重复反向引用 2 次或更多次
    • (?= 积极前瞻
      • ( 捕获第 2 组
        • (?:\d*?\1){1} 重复将反向引用匹配到组 1 m 次。这里m = 1
      • )关闭群
    • ) 关闭前瞻
    • \2 匹配第 2 组中捕获的内容以防止回溯
    • (?!\d*\1) 负前瞻,断言后面的组 1 不再出现
    • \d*匹配0+位数

    Regex demo | Python demo

    例如

    import re
    
    regex = r"^(\d)\1{2,},(?=((?:\d*?\1){1}))\2(?!\d*\1)\d*"
    test_str = ("111,222\n"
        "111,212")
    
    matches = re.finditer(regex, test_str, re.MULTILINE)
    
    for matchNum, match in enumerate(matches, start=1):
        print (match.group())
    

    输出

    111,212
    

    【讨论】:

      猜你喜欢
      • 2018-06-18
      • 1970-01-01
      • 2015-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-23
      • 1970-01-01
      • 2022-11-23
      相关资源
      最近更新 更多