Regex условное наблюдение - PullRequest
2 голосов
/ 30 мая 2019

Мой входной текстовый файл имеет вид

A={5,6},B={2},C={3}
B={2,4}
A={5},B={1},C={3}
A={5},B={2},C={3,4,QWERT},D={TXT}

Я хотел бы сопоставить все строки, где A = 5, B = 2 и C = 3.Уловка в том, что если переменная не упомянута, то эта переменная может принимать любое значение, и, следовательно, эта строка также должна соответствовать.

Выше должно совпадать со строками 1,2 и 4.

Iпробовал

.*?(?:(?=A)A\{.*?5).*?(?:(?=B)B\{.*?2).*?(?:(?=C)C\{.*?3)

https://regex101.com/r/NN9qk5/1

Но это не работает

Я буду использовать это регулярное выражение в коде Python 3.6.

1 Ответ

1 голос
/ 30 мая 2019

Если вы хотите решить это с помощью регулярного выражения, вы можете использовать

^
 (?!.*\bA={(?![^{}]*\b5\b))
 (?!.*\bB={(?![^{}]*\b2\b))
 (?!.*\bC={(?![^{}]*\b3\b))
.*

См. Демонстрационную версию regex

Смысл в том, чтобы провалить совпадение, еслиявляется ключом, который не содержит заданного числового значения внутри фигурных скобок.

Например, (?!.*\bA={(?![^{}]*\b5\b)) - это отрицательный запрос, который не дает совпадения, если непосредственно справа от текущего местоположения нет - .* - любого0+ символов, кроме символов перевода строки - \bA - целое слово A - ={ - ={ подстрока - (?![^{}]*\b5\b) - за которой не следует никаких символов 0+, кроме { и } и затем следует 5 как целое слово.

Пример использования в Python 3.6:

import re
s = """A={5,6},B={2},C={3}
B={2,4}
A={5},B={1},C={3}
A={5},B={2},C={3,4,QWERT},D={TXT}"""
given = { 'A': '5', 'B': '2', 'C': '3'}

reg_pattern = ''
for key,val in given.items():
    reg_pattern += r"(?!.*\b{}={{(?![^{{}}]*\b{}\b))".format(key,val)

reg = re.compile(reg_pattern)

for line in s.splitlines():
    if reg.match(line):
        print(line)

Вывод:

A={5,6},B={2},C={3}
B={2,4}
A={5},B={2},C={3,4,QWERT},D={TXT}

Обратите внимание на использование re.match, этот метод ищет только совпадение в начале строки, поэтому нет необходимости добавлять ^ якорь (соответствует началу строки).

...