查找子字符串的正则表达式

4

我正在尝试使用正则表达式查找子字符串的所有出现情况。这个子字符串由三部分组成,以一个或多个'A'开头,紧接着一个或多个'N',以一个或多个'A'结尾。假设有一个字符串'AAANAANABNA',如果解析该字符串,应该得到两个子字符串'AAANAA''AANA'作为输出。因此,我尝试了以下代码。

import regex as re
reg_a='A+N+A+'
s='AAANAANABNA'
sub_str=re.findall(reg_a,s,overlapped=True)
print(sub_str)

我得到了以下输出:

['AAANAA', 'AANAA', 'ANAA', 'AANA', 'ANA']

然而,我希望输出结果为:

['AAANAA', 'AANA']

也就是说,第一个匹配的字符串末尾的 A 应该成为下一个匹配字符串开头的 A。 我该如何实现这个功能,有什么想法?
3个回答

4

请确保左侧没有 A

>>> reg_a='(?<!A)A+N+A+'
>>> print( re.findall(reg_a,s,overlapped=True) )
['AAANAA', 'AANA']

(?<!A)A+N+A+匹配:

  • (?<!A)是一个负向后瞻,用于匹配不紧跟着A的位置
  • A+ - 匹配一个或多个A
  • N+ - 匹配一个或多个N
  • A+ - 匹配一个或多个A

请注意,您也可以使用re来获取匹配结果:

>>> import re
>>> re_a = r'(?=(?<!A)(A+N+A+))'
>>> print( re.findall(re_a, s) )
['AAANAA', 'AANA']

我从未使用过 overlapped=True,学到了新东西。++ - The fourth bird

4

一种选择是在不重叠的正向先行断言中使用带有捕获组的负向后行断言。re.findall 将返回捕获组的值。

(?=(?<!A)(A+N+A+))
  • (?= 正向先行断言,断言右侧内容为
    • (?<!A) 负向先行断言,断言左侧内容不为 A
    • (A+N+A+) 匹配指定模式
  • ) 关闭先行断言

正则表达式演示 | Python演示

import re
s = "AAANAANABNA"
pattern = r"(?=(?<!A)(A+N+A+))"
print(re.findall(pattern, s))

输出

['AAANAA', 'AANA']

或者像@anubhava建议的那样,将后顾和前瞻分开:

(?<!A)(?=(A+N+A+))

正则表达式演示 | Python演示


1
我认为这比第三方正则表达式略胜一筹?我都点赞了,我也很喜欢这个问题=) - JvdV
我无法确定,您是否打算使用正则表达式pypi模块来实现某种模式? - The fourth bird
1
(?<!A)(?=(A+N+A+)) 可能会更快地匹配相同的内容。 - anubhava
1
@Thefourthbird,感谢您分享优秀的代码和演示,祝贺! - RavinderSingh13

4

以下是使用 re 模块实现此操作的更简单方法。我们只需要在末尾有1个或多个 A 的前瞻,并且必须使用两个捕获组:

>>> import re
>>> s = 'AAANAANABNA'
>>> [''.join(x) for x in re.findall(r'(A+N+)(?=(A+))', s)]
['AAANAA', 'AANA']

正则表达式演示


1
很棒的发现,加入这些群组 ++ - The fourth bird

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接