Python регулярное выражение, которое повторяется \ d количество раз - PullRequest
0 голосов
/ 01 мая 2020

Используя python regex, я пытаюсь сопоставить столько чисел, сколько p, чем число di git, впервые сопоставленное с шаблоном.

Пример ввода

1pp
2p
3ppp
4ppppppppp

Ожидаемый результат

1p
None
3ppp
4pppp

Код проб Я попробовал следующий код, где я использую именованную группу и даю имя 'dig' для совпавшего di git, теперь я хочу использовать dig в повторении {m}. Но следующий код не находит соответствия в pattern.

pattern = "2pppp"
reTriple = '((?P<dig>\d)p{(?P=dig)})'
regex = re.compile(reTriple,re.IGNORECASE)
matches = re.finditer(regex,pattern)

Я думаю, проблема в том, что повтор {m} ожидает int m, где dig - строка. Но я не могу найти способ объединить int в строку, сохраняя его int! Я пробовал кастовать следующим образом:

reTrip = '((?P<dig>\d)p{%d}'%int('(?P=dig)')+')'

Но я получаю следующую ошибку:

ValueError: invalid literal for int() with base 10: '(?P=dig)'

Я застрял. Может кто-нибудь, пожалуйста, руководство.

И это странно, что если я вместо этого сломаю reTriple следующим образом: сначала сохраните совпавший di git в переменной, а затем объедините эту переменную в reTriple, это сработает, и ожидаемый результат будет достигнуты. Но это обходной путь, и я ищу лучший метод.

reTriple = '(?P<dig>\d)'
dig = re.search(reTriple , pattern).group('dig')
reTriple = reTriple + '(p{1,' + dig + '})'

Ответы [ 4 ]

1 голос
/ 01 мая 2020

Вы также можете выполнять чистые строковые операции, не завися от какого-либо модуля для упомянутых строк в вопросе (цифры <10): </p>

def val_txt(txt):
    dig = int(txt[0])
    rest_val = 'p' * dig
    return f'{dig}{rest_val}' if txt[1:1+dig] == rest_val else None

print(val_txt('1ppp'))
# 1p
1 голос
/ 01 мая 2020

Похоже, что вы пытаетесь в основном сводиться к: (\d+)p{\1}, где вы бы использовали группу захвата 1 в качестве ввода для того, как часто вам нужно совпадать с "p". Однако первая группа захвата, кажется, возвращается как текст (не цифра c), в результате чего вы не найдете результатов. Посмотрите, например, здесь .

Может быть, это поможет разделить это на две операции. Например:

import re

def val_txt(txt):
    i = int(re.search(r'\d+', txt).group(0))
    fnd = re.compile(fr'(?i)\d+p{{{i}}}')
    if fnd.search(txt):
        return fnd.search(txt).group(0)

print(val_txt('2p'))
0 голосов
/ 01 мая 2020

Вот одношаговое решение для регулярных выражений, которое использует лямбда-функцию для проверки, достаточно ли p для сопоставления цифр в начале строки; если он есть, он возвращает соответствующую строку (например, 1p или 3ppp), в противном случае он возвращает пустую строку:

import re

strs = ['1pp',
        '2p',
        '3ppp',
        '4ppppppppp'
        ]

for s in strs:
    print(re.sub(r'^(\d+)(p+).*', lambda m: m.group(1) + m.group(2)[:int(m.group(1))] if len(m.group(2)) >= int(m.group(1)) else '', s))

Вывод:

1p

3ppp
4pppp
0 голосов
/ 01 мая 2020

Привет, вы можете сделать еще один подход, например: without regex:

from typing import Union
def  test(txt: str, var: str ='p') -> Union[str, None]: 
    var_count = txt.count(var)
    number = int(txt[0:len(txt) - var_count:]) 
    if number <= var_count: 
        return f'{number}{number * var}' 

    return None 


Давайте проверим вывод:

t = ['1pp', '2p', '3ppp', '4ppppppppp', '10pppppppppp']             

for i in t: 
    print(test(i)) 

1p
None
3ppp
4pppp
10pppppppppp


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...