Пустое пространство не найдено Regex Python

У меня возникла небольшая проблема при попытке найти подстроку внутри строки с помощью регулярного выражения в Python. Рассмотрим следующую строку:

repr(a) = '\n02/07/2023, 14:52\nTest\nTest\nFin\n'

Я хотел бы найти подстроку от 2\n до \nFin\n. Обратите внимание, что он всегда будет заканчиваться на \nFin\n, но не всегда будет начинаться на 2\n. На самом деле он будет начинаться с X\n, где X — любой символ, отличный от пробела.

Вот таким образом мой код:

import re

a = """
02/07/2023, 14:52
Test
Test
Fin
"""

match = re.sub(r'[^ ]\n(.+)\n' + 'Fin' +'\n',r'** \1 **', a)

[^ ]: любой символ, не являющийся пробелом. \n(.+)\n' + 'Fin' +'\n': \n, за которым следует символ anny до \nFin\n.

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

Есть идеи? Проблема, кажется, исходит из пробела. Однако я пробовал разные решения, такие как «все цифры или буквы, за которыми следует \n», но не смог добиться успеха.

Что значит "не работает"? Он находит совпадение и заменяет его.

Wiktor Stribiżew 05.07.2023 22:02

Вы просто пытаетесь удалить две строки, содержащие «Test»?

CAustin 06.07.2023 01:23
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
2
54
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Согласен с Виктором, нужно знать в чем проблема. Кажется, работает. Вот что я вижу:

re.search(r'[^ ]\n(.+)\n' + 'Fin' +'\n', a)

показывает совпадение:

t\nTest\nFin\n

Это заменяется вашей строкой, создавая это:

02/07/2023, 14:52
Tes** Test **

это именно то, что я получаю от вызова re.sub.

Кажется, вы ожидаете, что (.+) будет соответствовать обеим строкам «Test», но точка не соответствует новой строке.

Ответ принят как подходящий

Я не уверен на 100% в вашем ожидаемом результате, но я подозреваю, как прокомментировал @samkamin, источник вашей проблемы в том, что . не соответствует новым строкам. Вместо этого вам нужно будет использовать [\s\S] (пробел и не пробел) для соответствия символу новой строки*, например:

>>> match = re.sub(r'\n.*[^ ]\n([\s\S]+)\nFin\n', r'** \1 **', a)
>>> print(match)
** Test
Test **
>>> 

Я добавил новую строку и .* в начале, чтобы отбросить начальную новую строку в вашей тестовой строке и отметке времени, поскольку вы сказали, что хотите, чтобы было то, что было между отметкой времени и \nFin.

* Это расширение Python. Базовое регулярное выражение в других контекстах потребует (\n|.), но это неэффективно.

Пожалуйста, не используйте (.|\n)+, потому что это очень неэффективно. Лучше использовать .+ с re.S или [\s\S]+

The fourth bird 05.07.2023 23:49

@Thefourthbird Спасибо, что научил меня кое-чему!

Vercingatorix 05.07.2023 23:52

@Thefourthbird Я включил ваше предложение.

Vercingatorix 07.07.2023 15:45

Если я запускаю предоставленный код, я получаю следующий вывод.

02/07/2023, 14:52
Tes** Test **

Ошибка в вашем коде заключается в том, что re.sub заменяет совпадающее значение, а не только захваченное значение.

Итак, это соответствует следующему.

t
Test
Fin

"... Я хочу найти подстроку от 2\n до \nFin\n. ..."

Вы можете использовать однолинейный режим, также называемый точечным режимом.
Это приведет к тому, что . будет дополнительно соответствовать разделителям новой строки.

Вы можете использовать следующий шаблон.

[^ \r\n]$[\r\n]+^(.+?)[\r\n]+^Fin$

$ и ^ здесь обозначают конец и начало строки соответственно.

Вы можете использовать функцию Pattern.search, чтобы вернуть первое совпадение и захваченное значение из a.

a = """
02/07/2023, 14:52
Test
Test
Fin
"""

pattern = re.compile(r'[^ \r\n]$[\r\n]+^(.+?)[\r\n]+^Fin$', flags=re.M | re.S)
matches = pattern.search(a)

print(matches.group(1))

Выход

Test
Test

И, если у вас есть текст с несколькими вхождениями, вы можете использовать функцию Pattern.finditer.

a = """
02/07/2023, 14:52
Test
Test
Fin

02/07/2023, 14:52
ABC
123
Fin

02/07/2023, 14:52
DEF
456
Fin
"""

pattern = re.compile(r'[^ \r\n]$[\r\n]+^(.+?)[\r\n]+^Fin$', flags=re.M | re.S)
matches = pattern.finditer(a)

for match in matches:
    print(match.group(1))

Выход

Test
Test
ABC
123
DEF
456

Другие вопросы по теме