带有“命名捕获组”的正则表达式,用于捕获模式或备用模式

2024-05-14 20:14:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我试着用一个独特的正则表达式

either: ' PIC S9(17).'            # with 'S9(17)'      in Named Capture Group pic
either: ' PIC S9(13)V9(2).'       # with 'S9(13)V9(2)' in Named Capture Group pic
either: ' PIC S9(9)V9(2) COMP-3.' # with 'S9(9)V9(2)'  in Named Capture Group pic
either: ' PIC X(16).'             # with 'X(16)'       in Named Capture Group pic

r'\s*PIC\s+(?P<pic>\S+)' 除了“PICS9(9)V9(2)COMP-3”,我什么都听懂了

r'\s*PIC\s+(?P<pic>\S+) COMP-3' 我只听到‘图S9(9)V9(2)COMP-3’

这是我的Python代码:

import re
def get_pics(data, pic):
    base = r'^(?P<level>\d{2})\s+(?P<name>\S+)'
    end = r'\.$'
    pformat = "({})?"
    pattern = re.compile(base + pformat.format(pic) + end)

    for row in data.strip().split('\n'):
        re_match = pattern.match(row.strip())
        if not re_match:
            print(' => NOP:\n    ', row)
        else:
            match = re_match.groupdict()
            print('ok:', match)

data = """
   12 M-AR03-MONTANT-RDJ                 PIC S9(17).
   12 M-AR03-COMPTE-RDJ                  PIC X(8).
  09 M-N014-INC-CHARG-AMT-FSOL           PIC S9(9)V9(2) COMP-3.
  09 M-N014-CHARGE-TYPE-FSOL             PIC X(5).
"""

因此,我们得到:

>>> get_pics(data, r'\s*PIC\s+(?P<pic>\S+)')
ok: {'level': '12', 'name': 'M-AR03-MONTANT-RDJ', 'pic': 'S9(17)'}
ok: {'level': '12', 'name': 'M-AR03-COMPTE-RDJ', 'pic': 'X(8)'}
 => NOP:
       09 M-N014-INC-CHARG-AMT-FSOL  PIC S9(9)V9(2) COMP-3.
ok: {'level': '09', 'name': 'M-N014-CHARGE-TYPE-FSOL', 'pic': 'X(5)'}
>>>

>>> get_pics(data, r'\s*PIC\s+(?P<pic>\S+) COMP-3')
 => NOP:
     12 M-AR03-MONTANT-RDJ         PIC S9(17).
 => NOP:
        12 M-AR03-COMPTE-RDJ       PIC X(8).
ok: {'level': '09', 'name': 'M-N014-INC-CHARG-AMT-FSOL', 'pic': 'S9(9)V9(2)'}
 => NOP:
       09 M-N014-CHARGE-TYPE-FSOL  PIC X(5).
>>>

奇怪的是在{a1}中{} 匹配所有4行:

PIC S9(17).
PIC S9(13)V9(2).
PIC S9(9)V9(2) COMP-3.
PIC X(16).

如果我尝试第四个bird正则表达式,我会得到:

In [2]: get_pics(data, r'\bPIC (?P<pic>(?:[A-Z]\d*\(\d+\))+)[^.\r\n]*\.') 
   ...:                                                                                                                            
 => NOP:
     12 M-AR03-MONTANT-RDJ          PIC S9(17).
 => NOP:
        12 M-AR03-COMPTE-RDJ           PIC X(8).
 => NOP:
       09 M-N014-INC-CHARG-AMT-FSOL    PIC S9(9)V9(2) COMP-3.
 => NOP:
       09 M-N014-CHARGE-TYPE-FSOL      PIC X(5).

In [3]:    

Tags: inredatamatchlevelnopcompv9
3条回答

我修改了您的基本模式,在末尾包含空格,并为pic创建了一个不同的模式

pat2 = r'(?P<level>\d{2})\s+(?P<name>\S+)\s+'
picpat = r'PIC\s(?P<pic>[^.\s]+)'

picpat匹配'PIC '之后的任何内容,直到它变成一个点或空白

Regular expression visualization

我使用一个f字符串将函数稍作修改,将其与pic模式相结合,在匹配项上而不是行上进行迭代

def get_pics(data,pic):
    pat2 = r'(?P<level>\d{2})\s+(?P<name>\S+)\s+'
    pattern = f'{pat2}{pic}'
    #pattern = '{}{}'.format(pat2,pic)
    pattern = re.compile(pattern)
    for match in pattern.finditer(data):
        print(match.groupdict())


>>> get_pics(data,picpat)
{'level': '12', 'name': 'M-AR03-MONTANT-RDJ', 'pic': 'S9(17)'}
{'level': '12', 'name': 'M-AR03-COMPTE-RDJ', 'pic': 'X(8)'}
{'level': '09', 'name': 'M-N014-INC-CHARG-AMT-FSOL', 'pic': 'S9(9)V9(2)'}
{'level': '09', 'name': 'M-N014-CHARGE-TYPE-FSOL', 'pic': 'X(5)'}
>>> 

考虑到你的例子有限,我不明白为什么以下是不够的:

r'\sPIC\s((?:(?:[SV]\d|X))?\((?:\d+)\))+( COMP-3)?\.'

例如,如果在您的示例中总是只有1个空格,那么就没有必要使用\s+

类似地,如果您不告诉我们该位如何变化(例如,它是COMP-后跟任意位数的整数?好的,使用COMP-\d+),那么没有理由不在正则表达式中使用文字COMP-3

如果您想用这些值捕获组pic,并且在最后应该有at点,您可以使模式更具体一些:

\bPIC (?P<pic>(?:[A-Z]\d*\(\d+\))+)[^.\r\n]*\.
  • \bPIC 单词边界,匹配PIC和空格
  • (?P<pic>命名组pic
    • (?:非捕获组
      • [A-Z]\d*\(\d+\)匹配字符a-Z、阿片数字和括号之间的1+数字
    • )+关闭组,重复1+次
  • )封闭组pic
  • [^.\r\n]*\.将除点和换行符以外的任何字符匹配0+次,并匹配尾随的点

Regex demoPython demo


在代码中,不必使用?使组成为可选的。组pic的模式已经包含匹配的结束点,因此可以省略end = r'\.$'

在第一个和第二个模式之间,可以使用[^\S\r\n]+匹配一个或多个空格,该空格将匹配除换行符以外的任何空格字符的1倍或更多倍


比如说

import re
def get_pics(data, pic):
    base = r'(?P<level>\d{2})\s+(?P<name>\S+)'
    pattern = re.compile(f"^{base}[^\S\r\n]+{pic}$")
    for row in data.strip().split('\n'):
        re_match = pattern.match(row.strip())
        if not re_match:
            print(' => NOP:\n    ', row)
        else:
            match = re_match.groupdict()
            print('ok:', match)

data = """
   12 M-AR03-MONTANT-RDJ                 PIC S9(17).
   12 M-AR03-COMPTE-RDJ                  PIC X(8).
  09 M-N014-INC-CHARG-AMT-FSOL           PIC S9(9)V9(2) COMP-3.
  09 M-N014-CHARGE-TYPE-FSOL             PIC X(5).
"""

get_pics(data, r'\bPIC (?P<pic>(?:[A-Z]\d*\(\d+\))+)[^.\r\n]*\.')

输出

ok: {'level': '12', 'name': 'M-AR03-MONTANT-RDJ', 'pic': 'S9(17)'}
ok: {'level': '12', 'name': 'M-AR03-COMPTE-RDJ', 'pic': 'X(8)'}
ok: {'level': '09', 'name': 'M-N014-INC-CHARG-AMT-FSOL', 'pic': 'S9(9)V9(2)'}
ok: {'level': '09', 'name': 'M-N014-CHARGE-TYPE-FSOL', 'pic': 'X(5)'}

相关问题 更多 >

    热门问题