Regex 子字符串的可选结束部分的正则表达式

Regex 子字符串的可选结束部分的正则表达式,regex,string,python-3.x,Regex,String,Python 3.x,考虑以下(高度简化的)字符串: 这是一个重复的'abc'模式,除非在开头缺少'c' 我通过使用re.findall(),寻找一个正则表达式,它可以为我提供以下匹配: 因此,上面的字符串有4个匹配项'abc'——尽管第一个匹配项作为特例,因为'c'缺失 我最简单的尝试是尝试捕获'a'和'b'并对'c'使用可选捕获: re.findall(r'(a).*?(b).*?(c)?', 'a b a b c a b c a b c') 我得到: [('a', 'b', ''), ('a', 'b', '

考虑以下(高度简化的)字符串:

这是一个重复的
'abc'
模式,除非在开头缺少
'c'

我通过使用
re.findall()
,寻找一个正则表达式,它可以为我提供以下匹配:

因此,上面的字符串有4个匹配项
'abc'
——尽管第一个匹配项作为特例,因为
'c'
缺失

我最简单的尝试是尝试捕获
'a'
'b'
并对
'c'
使用可选捕获:

re.findall(r'(a).*?(b).*?(c)?', 'a b a b c a b c a b c')
我得到:

[('a', 'b', ''), ('a', 'b', ''), ('a', 'b', ''), ('a', 'b', '')]
显然,它只是忽略了
c
。对
'c'
使用非可选捕获时,搜索会提前跳过,并在第二个
'a b c'
-子字符串中错过
'a'
'b'
。这将导致3个错误匹配:

[('a', 'b', 'c'), ('a', 'b', 'c'), ('a', 'b', 'c')]

我还尝试了其他几种技术(例如,
)(?由于
a
b
c
都是占位符,您无法知道它们是单个字符、字符序列还是其他任何东西,因此需要使用一个标记来确保模式不会溢出到同一字符串中的其他匹配项,并且由于
c
是可选的,只需用
(?:…)?
可选非捕获组将其包装起来:

(a)(?:(?!a|b).)*(b)(?:(?:(?!a|b|c).)*(c))?
   ^^^^^^^^^^^^^   ^^^ ^^^^^^^^^^^^^^    ^

详细信息

  • (a)
    -第1组捕获一些
    a
  • (?:(?!a | b)。*
    -与任何字符匹配的标记,该字符不启动
    a
    b
    序列
  • (b)
    -第2组捕获一些
    b
  • (?:
    -启动可选的非捕获组,重复1或0次
    • (?:(?!a | b | c)。*
      -匹配任何字符的标记,但不匹配以
      a
      b
      c
      模式开头的换行符
    • (c)
      -第3组捕获一些
      c
      模式
  • )?
    -可选非捕获组的结尾
要获得所需的元组列表,您需要使用以下方法自行构建:

import re
r = r'(a)(?:(?!a|b).)*(b)(?:(?:(?!a|b|c).)*(c))?'
s = 'a b a b c a b c a b c'
# print(re.findall(r,s))
# That one is bad: [('a', 'b', ''), ('a', 'b', 'c'), ('a', 'b', 'c'), ('a', 'b', 'c')]
print([(a,b,c) if c else (a,b) for a,b,c in re.findall(r,s)])
# This one is good: [('a', 'b'), ('a', 'b', 'c'), ('a', 'b', 'c'), ('a', 'b', 'c')]

查看

re.findall
完成其工作后,您需要“手动”删除空元组元素。您确定需要正则表达式来解析日志吗?@WayneWerner Yes:)绝对必要。您的示例过于简化,因此很难提供可靠的答案。我相信问题在于您在a、b和c之间使用了
*?
通配符。对于初学者,请尝试使用
+?
,这样懒惰运算符就不会导致它匹配零个字符并重新启动模式。此正则表达式格式适用于R
^ab|abc
示例:
x=“ababcabc”
stringr::str_extract_all(x,“^ab|abc”)
[1]“ab”“abc”“abc”“abc”
不确定在python中是如何实现的。谢谢。正则表达式适用于简单的事情(至少).我想,我试图做的事情不能用有限状态机规则来完成(它似乎需要更多的分支逻辑)。我刚刚尝试了你的方法,但它仍然遗漏了部分。我将寻求另一种方法。接受,因为我学到了一些新东西:-)好的,你们只发布了非常简单的示例,我尽可能地概括了这个示例。regexp需要精确性,并且需要精确的要求和x规范。祝你们好运。
(a)(?:(?!a|b).)*(b)(?:(?:(?!a|b|c).)*(c))?
   ^^^^^^^^^^^^^   ^^^ ^^^^^^^^^^^^^^    ^
import re
r = r'(a)(?:(?!a|b).)*(b)(?:(?:(?!a|b|c).)*(c))?'
s = 'a b a b c a b c a b c'
# print(re.findall(r,s))
# That one is bad: [('a', 'b', ''), ('a', 'b', 'c'), ('a', 'b', 'c'), ('a', 'b', 'c')]
print([(a,b,c) if c else (a,b) for a,b,c in re.findall(r,s)])
# This one is good: [('a', 'b'), ('a', 'b', 'c'), ('a', 'b', 'c'), ('a', 'b', 'c')]