Я пытаюсь построить эффективную регулярную регрессию, которая объединяет несколько строк со следующими ограничениями в одну строку.
Положительные образцы:
Пример 1:
My favorite books are as follows:\nA great book\nThe Effective Book onscala.io\nTest Book\n
Матчи:
My favorite books are as follows:\nA great book\nThe Effective Book onscala.io\nTest Book\n
Пример 2:
My favorite books are as follows:\nA great book\nanother sentence\nAnother book\n
Соответствует: строки до тех пор, пока первая буква каждой строки не станет заглавной.
My favorite books are as follows:\nA great book\n
Отрицательный образец:
My favorite books are as follows:\na great book\nanother sentence\n
Не соответствует
Я создал следующее регулярное выражение, но оно соответствует каждой строке независимо от того, начинается ли она с заглавной буквы.
(^[A-Z].*:)\n(^[A-Z].+(?:\s+[a-zA-Z0-9,./ ]+){1,10})
Если бы приведенное выше регулярное выражение соответствовало ожидаемым строкам, я бы заменил \n
пробелом и запятой.
Я намеревался (^[A-Z].+(?:\s+[a-zA-Z0-9,./ ]+){1,10}
сопоставить строку, начинающуюся с заглавной буквы, с 10 или менее словами. Судя по вашему вопросу, похоже, что регулярное выражение подсчитывает строки, а не слова в строке.
вы намеревались получить частичное совпадение? Я видел, что @anubhava обновил ваш вопрос, но не увидел ничего, что изначально указывало бы на этот вариант использования.
@Thatalent: Я внес изменения в форматирование только для того, чтобы оно было лучше читаемо.
Извини, @anubhava, ты прав. Я понял, что ОП добавил в свою редакцию второй вариант использования, а я просто пропустил его. Однако на мой вопрос я получил ответ, и спасибо за четкое редактирование!
Вы можете использовать это регулярное выражение для получения совпадений:
^[A-Z][^:\n]*:\n(?:[A-Z][\w,./-]*(?:\h+[\w,./-]+){0,9}\n)+
Детали регулярного выражения:
^
: начать новую строку.[A-Z]
: Сопоставьте заглавную букву.[^:\n]*
: сопоставьте 0 или более символов, кроме :
.:\n
: совпадение двоеточия, за которым следует разрыв строки.(?:
: Запустить группу без захвата.
[A-Z][\w,./-]*
: Сопоставьте первое слово, которое должно начинаться с заглавной буквы.(?:\h+[\w,./-]+){0,9}
: Сопоставьте от 0 до 9 других слов, разделенных более чем 1 пробелом.\n
: Сопоставить разрыв строки.)+
: Завершить группу без захвата. Повторите эту группу 1+ раз.Я думаю, вы можете обновить регулярное выражение, чтобы избежать частичных совпадений в строках, у которых вторая строка действительна, а третья — нет.
Я считаю, что ОП хочет частичных совпадений. См. пример 2 в вопросе.
Спасибо за разъяснения. Думаю, я это пропустил или просто изначально увидел устаревшую версию вопроса.
Огромное спасибо за решение и объяснение! Он делает именно то, что я хотел.
Прежде всего используйте этот сайт для тестирования: https://regex101.com/
Это сэкономит вам много времени.
Это должно дать вам то, что вы хотите, хотя вам нужно убедиться, что вы не используете многострочный флаг, чтобы он не соответствовал вашему отрицательному регистру.
^([A-Z](.*\h?){0,9}\n?)+
Вы можете заменить .*
более ограниченным шаблоном для одной строки (исключая первый символ), например:
^(([A-Z])([\w:.,-]*\h?){0,9}\n?)+
Здесь важно то, что вам нужно начальное совпадение, но вам также нужно совпадение n, чтобы убедиться, что вы частично соответствуете своему отрицательному регистру. Я добавил \h
, чтобы соответствовать только табуляциям и пробелам, но не новым строкам.
Вот демо
Самые большие проблемы с вашим регулярным выражением:
m
. Это потому, что он будет соответствовать только началу всей строки, если вы не укажете ему, чтобы он соответствовал началу каждой строки (это то, что означает многострочный аспект)..+(?:\s+[a-zA-Z0-9,./ ]+)
это излишне и на самом деле не дает вам того, что вы думаете. .+
по сути соответствует всей строке, кроме последнего слова (в зависимости от пробела), а затем соответствует [a-zA-Z0-9,./ ]
последнему слову или символу, а затем повторяется в течение 15 строк.Проблема 2 не так уж и плоха, потому что по большей части она делает то, что вы хотите, но то, что я предлагаю, должно быть достаточно скудным, чтобы вы могли на его основе построить и столкнуться с проблемами позже. Опять же, вы можете использовать исходное регулярное выражение, если удалить второе ^
, но я думаю, что что-то может испортиться, потому что в нем много ненужных вещей.
Я обновил вашу демо-версию, чтобы использовать образцы из вопроса, но она не удалась: regex101.com/r/UPR5nD/2
Да, я обновил его. Кажется, я пропустил второй вариант использования OP или увидел вопрос до того, как он был добавлен.
Это очень помогло выявить проблемы с моим регулярным выражением. Очень признателен за ваш подробный ответ и демо-версию.
Где ваше регулярное выражение ограничивает последующие строки 10 словами или меньше? Почему у вас есть ограничение на 15 строк в последующих строках? Вы не упомянули об этом в своем описании.