Как сопоставить строки, начинающиеся с заглавной буквы и содержащие от 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 пробелом и запятой.

Где ваше регулярное выражение ограничивает последующие строки 10 словами или меньше? Почему у вас есть ограничение на 15 строк в последующих строках? Вы не упомянули об этом в своем описании.

Chris Maurer 28.08.2024 22:40

Я намеревался (^[A-Z].+(?:\s+[a-zA-Z0-9,./ ]+){1,10} сопоставить строку, начинающуюся с заглавной буквы, с 10 или менее словами. Судя по вашему вопросу, похоже, что регулярное выражение подсчитывает строки, а не слова в строке.

vish 28.08.2024 23:02

вы намеревались получить частичное совпадение? Я видел, что @anubhava обновил ваш вопрос, но не увидел ничего, что изначально указывало бы на этот вариант использования.

Thatalent 29.08.2024 15:44

@Thatalent: Я внес изменения в форматирование только для того, чтобы оно было лучше читаемо.

anubhava 29.08.2024 15:56

Извини, @anubhava, ты прав. Я понял, что ОП добавил в свою редакцию второй вариант использования, а я просто пропустил его. Однако на мой вопрос я получил ответ, и спасибо за четкое редактирование!

Thatalent 29.08.2024 19:31
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
91
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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+ раз.

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

Thatalent 28.08.2024 23:31

Я считаю, что ОП хочет частичных совпадений. См. пример 2 в вопросе.

anubhava 29.08.2024 04:53

Спасибо за разъяснения. Думаю, я это пропустил или просто изначально увидел устаревшую версию вопроса.

Thatalent 29.08.2024 19:32

Огромное спасибо за решение и объяснение! Он делает именно то, что я хотел.

vish 29.08.2024 19:53

Прежде всего используйте этот сайт для тестирования: 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 не так уж и плоха, потому что по большей части она делает то, что вы хотите, но то, что я предлагаю, должно быть достаточно скудным, чтобы вы могли на его основе построить и столкнуться с проблемами позже. Опять же, вы можете использовать исходное регулярное выражение, если удалить второе ^, но я думаю, что что-то может испортиться, потому что в нем много ненужных вещей.

Я обновил вашу демо-версию, чтобы использовать образцы из вопроса, но она не удалась: regex101.com/r/UPR5nD/2

jhnc 29.08.2024 02:31

Да, я обновил его. Кажется, я пропустил второй вариант использования OP или увидел вопрос до того, как он был добавлен.

Thatalent 29.08.2024 19:34

Это очень помогло выявить проблемы с моим регулярным выражением. Очень признателен за ваш подробный ответ и демо-версию.

vish 29.08.2024 19:57

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

Как изменить нижний регистр на верхний регистр при нескольких вариантах выбора в режиме регулярного выражения
String#gsub, как использовать совпадение в атрибуте replace, а также вставлять линию разрыва
Bash-скрипт для сокращения имени файла до длины не более n, но без обрезки целых слов
Как извлечь часть строки с помощью sed?
Как использовать регулярное выражение для извлечения набора определенных подстрок?
Негативный просмотр, похоже, не работает должным образом
Объединить многострочные строки в фрейме данных pandas на основе шаблона регулярного выражения
Регулярное выражение для текста, разделенного запятыми, с необязательными двойными кавычками, которые могут содержать кавычки, экранированные обратной косой чертой
Почему эта замена регулярного выражения с использованием захвата зависает в этом быстром коде?
Токенизация XSLT с помощью регулярного выражения для токенизации только в том случае, если за точкой с запятой не следует пробел и число