Захватите ВСЕ строки в скрипте Python с помощью регулярных выражений - PullRequest
2 голосов
/ 04 марта 2020

Этот вопрос был вдохновлен моими неудачными попытками после попытки адаптировать этот ответ: RegEx: захват значений между кавычками

Рассмотрим следующий сценарий Python (t.py):

print("This is also an NL test")
variable = "!\n"
print('And this has an escaped quote "don\'t"  in it ', variable,
      "This has a single quote ' but doesn\'t end the quote as it" + \
      " started with double quotes")
if "Foo Bar" != '''Another Value''':
    """
    This is just nonsense
    """
    aux = '?'
    print("Did I \"failed\"?", f"{aux}")

Я хочу захватить все строки в нем, как:

  • This is also an NL test
  • !\n
  • And this has an escaped quote "don\'t" in it
  • This has a single quote ' but doesn\'t end the quote as it
  • started with double quotes
  • Foo Bar
  • Another Value
  • This is just nonsense
  • ?
  • Did I \"failed\"?
  • {aux}

Я написал еще один Python скрипт с использованием модуля re и из моих попыток регулярных выражений большинство из них находит:

import re
pattern = re.compile(r"""(?<=(["']\b))(?:(?=(\\?))\2.)*?(?=\1)""")
with open('t.py', 'r') as f:
    msg = f.read()
x = pattern.finditer(msg, re.DOTALL)
for i, s in enumerate(x):
    print(f'[{i}]',s.group(0))

со следующим результатом:

  • [0] And this has an escaped quote "don\'t" in it
  • [1] This has a single quote ' but doesn\'t end the quote as it started with double quotes
  • [2] Foo Bar
  • [3] Another Value
  • [4] Did I \"failed\"?

Чтобы улучшить свои ошибки, я не смог также полностью воспроизвести то, что Я могу найти с regex101.com :

enter image description here

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

1 Ответ

3 голосов
/ 04 марта 2020

Поскольку вы хотите сопоставить ''' или """ или ' или " в качестве разделителя, поместите все это в первую группу:

('''|"""|["'])

Не ставьте \b после него, потому что тогда он не будет совпадать со строками, когда эти строки начинаются с чего-то отличного от символа слова.

Поскольку вы хотите убедиться, что разделитель final не является рассматривается как начальный разделитель, когда двигатель запускает следующую итерацию, вам необходимо полностью сопоставить его (а не просто заглянуть в него).

Средняя часть, чтобы соответствовать чему угодно, кроме разделителя, может быть:

((?:\\.|.)*?)

Соберите все вместе:

('''|"""|["'])((?:\\.|.)*?)\1

, и нужный вам результат будет во второй группе захвата:

pattern = re.compile(r"""(?s)('''|\"""|["'])((?:\\.|.)*?)\1""")
with open('t.py', 'r') as f:
    msg = f.read()
x = pattern.finditer(msg)
for i, s in enumerate(x):
    print(f'[{i}]',s.group(2))

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

...