Как сопоставить строки, начинающиеся с заглавной буквы и содержащие от 1 до 10 слов в строке, с помощью регулярных выражений

Я пытаюсь построить эффективную регулярную регрессию, которая объединяет несколько строк со следующими ограничениями в одну строку.

  • Первые строки начинаются с заглавной буквы и заканчиваются двоеточием.
  • Остальные последовательные строки содержат от 1 до 10 слов; первое слово должно начинаться с заглавной буквы. Остальные слова могут быть смешанного регистра. Все слова в строке могут содержать такие символы, как ,-./

Положительные образцы:

Пример 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 пробелом и запятой.


91
2

Ответы:

Решено

Вы можете использовать это регулярное выражение для получения совпадений:

^[A-Z][^:\n]*:\n(?:[A-Z][\w,./-]*(?:\h+[\w,./-]+){0,9}\n)+

Демо RegEx

Детали регулярного выражения:

  • ^: начать новую строку.
  • [A-Z]: Сопоставьте заглавную букву.
  • [^:\n]*: сопоставьте 0 или более символов, кроме :.
  • :\n: совпадение двоеточия, за которым следует разрыв строки.
  • (?:: Запустить группу без захвата.
    • [A-Z][\w,./-]*: Сопоставьте первое слово, которое должно начинаться с заглавной буквы.
    • (?:\h+[\w,./-]+){0,9}: Сопоставьте от 0 до 9 других слов, разделенных более чем 1 пробелом.
    • \n: Сопоставить разрыв строки.
  • )+: Завершить группу без захвата. Повторите эту группу 1+ раз.

Прежде всего используйте этот сайт для тестирования: https://regex101.com/

Это сэкономит вам много времени.

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

^([A-Z](.*\h?){0,9}\n?)+

Вы можете заменить .* более ограниченным шаблоном для одной строки (исключая первый символ), например:

^(([A-Z])([\w:.,-]*\h?){0,9}\n?)+

Здесь важно то, что вам нужно начальное совпадение, но вам также нужно совпадение n, чтобы убедиться, что вы частично соответствуете своему отрицательному регистру. Я добавил \h, чтобы соответствовать только табуляциям и пробелам, но не новым строкам. Вот демо

Самые большие проблемы с вашим регулярным выражением:

  1. Без многострочного флага он ничему не соответствовал. Если вы используете веб-сайт, на который я ссылаюсь, вы можете увидеть, что второе начало метасимвола строки не работает без флага m. Это потому, что он будет соответствовать только началу всей строки, если вы не укажете ему, чтобы он соответствовал началу каждой строки (это то, что означает многострочный аспект).
  2. .+(?:\s+[a-zA-Z0-9,./ ]+) это излишне и на самом деле не дает вам того, что вы думаете. .+ по сути соответствует всей строке, кроме последнего слова (в зависимости от пробела), а затем соответствует [a-zA-Z0-9,./ ] последнему слову или символу, а затем повторяется в течение 15 строк.

Проблема 2 не так уж и плоха, потому что по большей части она делает то, что вы хотите, но то, что я предлагаю, должно быть достаточно скудным, чтобы вы могли на его основе построить и столкнуться с проблемами позже. Опять же, вы можете использовать исходное регулярное выражение, если удалить второе ^, но я думаю, что что-то может испортиться, потому что в нем много ненужных вещей.