正则表达式可选匹配模式

时间:2014-11-03 16:51:15

标签: python regex

我尝试使用?量词来匹配模式,只有它存在,但我无法按照我的意愿使用它。在下面的示例中,我尝试在AZAZZZ之后提取一对数字,其中ZZZ始终显示,但AZA是可选的。如果缺少AZA,我只想返回('', [zzz-value])对(空字符串而不是AZA值):

输入:

AZA:00zx---
ZZZ:32fd---
testxfiler
gsdkfklsd
fdsfsk
AZA:06x---
ZZZ:50----
gsdkfklsd
gsdkfklsd
fdsfsk
fdsfsk
gsdkfklsd
fdsfsk
ZZZ:32zzz----
fdsfsk
fdsfsk
gsdkfklsd
fdsfsk
AZA:46----
ZZZ:53---

期望的输出:

[(00,32), (06, 50), ('',32), (46,53)]

我的尝试:

re.findall('(?:AZA:([0-9]*))?.*?ZZZ:([0-9]*)', text, re.DOTALL)

我的输出:

[('00', '32'), ('', '50'), ('', '32'), ('', '53')

3 个答案:

答案 0 :(得分:3)

(?:AZA:(\d+).*?)?ZZZ:(\d+)

请参阅demo

import re
p = re.compile(ur'(?:AZA:(\d+).*?)?ZZZ:(\d+)', re.DOTALL)
test_str = u"AZA:00zx---\nZZZ:32fd---\ntestxfiler\ngsdkfklsd\nfdsfsk\nAZA:06x---\nZZZ:50----\ngsdkfklsd\ngsdkfklsd\nfdsfsk\nfdsfsk\ngsdkfklsd\nfdsfsk\nZZZ:32zzz----\nfdsfsk\nfdsfsk\ngsdkfklsd\nfdsfsk\nAZA:46----\nZZZ:53---"

re.findall(p, test_str)

答案 1 :(得分:1)

您不需要添加DOTALL修饰符

>>> text = """AZA:00zx---
ZZZ:32fd---
testxfiler
gsdkfklsd
fdsfsk
AZA:06x---
ZZZ:50----
gsdkfklsd
gsdkfklsd
fdsfsk
fdsfsk
gsdkfklsd
fdsfsk
ZZZ:32zzz----
fdsfsk
fdsfsk
gsdkfklsd
fdsfsk
AZA:46----
ZZZ:53---"""
>>> re.findall(r'(?:AZA:([0-9]+)[\S\s]*?)?ZZZ:([0-9]+)', text)
[('00', '32'), ('06', '50'), ('', '32'), ('46', '53')]

DEMO

[\S\s]*将匹配任何空格或非空格字符零次或多次。

为什么你的正则表达式无法正常工作?

(?:AZA:([0-9]*))?.*?ZZZ:([0-9]*)

我们都知道在DOTALL模式下,正则表达式中的点也会匹配偶数换行符。因此,通过将(?:AZA:([0-9]*))?设置为可选,以下.*?将匹配ZZZ:([0-9]*)之前存在的所有前面的字符。因此,通过在前面的可选组中包含以下.*?AZA:(\d+)匹配(如果它显示)并且将捕获AZA:后面的数字。现在,它不会做一场不必要的比赛。

答案 2 :(得分:1)

表单的正则表达式

(?:AZA:(\d+)[^\n]*\n)?(?:ZZZ:)(\d+)[^\n]*会有所帮助。

例如

>>>re.findall('(?:AZA:(\d+)[^\n]*\n)?(?:ZZZ:)(\d+)[^\n]*' ,x)
[('00', '32'), ('06', '50'), ('', '32'), ('46', '53')]
  • (?:AZA:(\d+)[^\n]*\n)?匹配:AZA:后跟数字\d+,后跟\n[^\n])以外的任何内容。最后的量词?确保整个组是可选的。数字在第1组中捕获

  • (?:ZZZ:)(\d+)[^\n]*匹配:ZZZ:后跟数字\d+以及\n以外的任何内容。第2组中捕获的数字

您错过了什么

re.findall('(?:AZA:([0-9]*))?.*?ZZZ:([0-9]*)', text, re.DOTALL)

整个(?:AZA:([0-9]*))?.*?应该是可选的

(?:AZA:([0-9]*))?.*?)?

后跟\n

更改你的正则表达式

re.findall('(?:AZA:([0-9]*).*?)?\nZZZ:([0-9]*)' ,x)

将输出

[('00', '32'), ('06', '50'), ('', '32'), ('46', '53')]