首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用“Named Group”进行正则表达式以捕获模式或备用模式

使用“Named Group”进行正则表达式以捕获模式或备用模式
EN

Stack Overflow用户
提问于 2020-02-17 01:25:56
回答 3查看 54关注 0票数 1

我尝试用一个独特的正则表达式来捕捉

代码语言:javascript
复制
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+)'时,除了‘PIC S9(9)V9(2) COMP-3’之外,我什么都能捕捉到。

使用r'\s*PIC\s+(?P<pic>\S+) COMP-3',我只捕获了‘PIC S9(9)V9(2) COMP-3’。

这是我的Python代码:

代码语言:javascript
复制
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).
"""

所以我们得到:

代码语言:javascript
复制
>>> 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)'}
>>>

代码语言:javascript
复制
>>> 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).
>>>

奇怪的是,在https://regex101.com/中,'\s*PIC\s+(?P<pic>\S+)'匹配所有4行代码:

代码语言:javascript
复制
PIC S9(17).
PIC S9(13)V9(2).
PIC S9(9)V9(2) COMP-3.
PIC X(16).

如果我尝试@ the -fourth bird正则表达式,我会得到:

代码语言:javascript
复制
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]:    
EN

回答 3

Stack Overflow用户

发布于 2020-02-17 01:33:21

如果您希望使用这些值捕获组pic,并且在末尾应该有一个点,那么可以使模式更具体一些:

代码语言:javascript
复制
\bPIC (?P<pic>(?:[A-Z]\d*\(\d+\))+)[^.\r\n]*\.

  • \bPIC单词边界,匹配数字和space
  • (?P<pic>命名组
    • (?:非捕获组
      • [A-Z]\d*\(\d+\)在parenthesis

之间匹配字符A-Z、操作位和PIC pic 1+

代码语言:javascript
复制
- `)+` Close group an repeat 1+ times

  • ) Close group pic
  • [^.\r\n]*\.匹配除点和换行符0+时间以外的任何字符,并匹配尾随的点

Regex demo | Python demo

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

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

例如

代码语言:javascript
复制
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]*\.')

输出

代码语言:javascript
复制
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)'}
票数 2
EN

Stack Overflow用户

发布于 2020-02-17 01:38:38

考虑到您的有限示例,我不明白为什么以下内容还不够:

代码语言:javascript
复制
r'\sPIC\s((?:(?:[SV]\d|X))?\((?:\d+)\))+( COMP-3)?\.'

例如,如果示例中始终只有1个空格,则不需要使用\s+

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

票数 1
EN

Stack Overflow用户

发布于 2020-02-17 02:24:14

我修改了你的基本模式,在最后加入了空格,并为pic设计了一个不同的模式。

代码语言:javascript
复制
pat2 = r'(?P<level>\d{2})\s+(?P<name>\S+)\s+'
picpat = r'PIC\s(?P<pic>[^.\s]+)'

picpat匹配'PIC '之后的任何内容,直到它到达一个点或空格。

我使用f字符串对函数进行了一些修改,将其与pic模式相结合,迭代匹配而不是行。

代码语言:javascript
复制
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)'}
>>> 
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60251161

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档