У меня есть текст со следующей структурой:
Round 1
some multiline text ...
Round 2
some multiline text ...
...
Round N
some multiline text ...
Я хотел бы сопоставить раунды с их многострочным текстом.
Ни одно из выражений не дает правильного результата:
(Round \ s \ d +) ((?! Round). *?)
(Круглый \ s \ d +) (. *?)
Кто-нибудь может мне помочь?
Заранее спасибо.





Символ точки (.) по умолчанию соответствует всем символам Кроме новой строки. Во многих языках вы можете использовать модификатор s, чтобы точка соответствовала символам все, включая символы новой строки. Это должно выглядеть примерно так:
/(Round\s\d+)(.*?)(Round\s\d+|$)/s
(Не уверен на 100%, что это регулярное выражение будет работать, я просто показываю вам, как использовать модификатор s.)
Редактировать: Протестировано на regexpal.com, похоже, работает.
Использование регулярного выражения непосредственно в нескольких строках может быть непростым (с точки зрения удобочитаемости и удобства обслуживания).
Я бы обработал текст построчно и использовал бы структуру данных для хранения всего, что было видно до сих пор. Вы можете сравнить это с обработкой электронной почты, когда у вас есть заголовки, тело и т. д.
Это вопрос C#?
(Круглый \ s \ d +) (. *?)
Используйте RegexOptions.Singleline
Однострочный Задает однострочный режим. Изменяет значение точки (.), Чтобы она соответствовала каждому символу (вместо каждого символа, кроме \ n).
И вам, вероятно, следует использовать Matches вместо Match.
. *? в вашем регулярном выражении не будет соответствовать абсолютно ничего, потому что после ленивой звезды нет ничего, чтобы заставить его повторяться более нуля раз
Редко, если вообще когда-либо правильно использовать неохотный квантификатор в качестве последней вещи в регулярном выражении. В этом регулярном выражении:
/(Round\s+\d+)(.*?)/s
... первое, что делает (.*?), это пытается сопоставить нулевые символы. Это совершенно законное совпадение, и, поскольку квантификатор неохотно, он останавливается прямо здесь. Если вы собираетесь сделать это таким образом, после (.*?) должно быть что-то вроде этого:
/(Round\s+\d+)(.*?)(Round\s+\d+)/s
Таким образом, (.*?) не может останавливаться на нулевых символах; он должен сопоставлять потребляющие символы, пока не достигнет места, где следующая часть регулярного выражения - (Round\s+\d+) - может взять верх. Но вы не хотите использовать это регулярное выражение, потому что оно потребляет часть того, что должно быть следующим совпадением. Придерживаясь этого формата, вы можете использовать опережающий просмотр в качестве конечного условия:
/(Round\s+\d+)(.*?)(?=Round\s+\d+|$)/s
Теперь он принудительно соответствует всей записи, но позиция совпадения остается в начале следующей записи, поэтому следующая попытка совпадения начнется там. (Обновлено: добавлен |$ в предварительный просмотр, чтобы соответствовать последней записи.)
Обновлено: Я тоже хотел прокомментировать ваше другое регулярное выражение:
/(Round\s+\d+)((?!Round).*?)/s
Здесь вместо использования положительного опережающего просмотра в качестве конечного условия похоже, что вы пытаетесь использовать упреждающий опережающий просмотр отрицательный. Чтобы это сработало, предварительный просмотр должен выполняться в каждой позиции, прежде чем точке будет разрешено использовать символ. Это означает, что точка должна быть заключена в круглые скобки с опережающим просмотром, а квантификатор находится вне их:
/(Round\s+\d+)((?:(?!Round).)*)/s
Вы также не можете использовать в этом регулярном выражении неохотный квантификатор по той же причине, что и другой.
Возможно, есть лучший способ сделать это, но мне нужно больше узнать о данных и ваших требованиях, прежде чем я смогу что-либо предложить.
(Обратите внимание, что я использовал синтаксис, подобный Perl, с разделителями косой черты и завершающим модификатором 's' для однострочного режима, потому что регулярные выражения часто сбивают с толку подсветку синтаксиса сайта без них.)
Это поможет с набором RegexOptions.SingleLine:
Round\s+\d+(.*?)(?=Round\s\d|$)
Алан, отличные советы по регулярным выражениям, мне не хватило практики с опережением.
/(Round\s+\d+)(.*?)(?=Round\s+\d+|$)/s делает именно то, что мне нужно.
/(Round\s+\d+)((?!Round).)*/s тоже работает, но каждая буква записывается отдельно.
Большое спасибо.
Чтобы более точно описать мои данные, вы можете посмотреть здесь, например: http://www.rsssf.com/tablesi/ital09.html
На самом деле мне нужно импортировать в свою базу данных всю информацию о раундах, матчах, результатах, их датах.
Мне нужно решить еще одну проблему: Как соотнести мои уже сохраненные команды с теми, которые находятся в результатах матчей. Например, у меня в БД есть команда «Интер». Но результат матча может выглядеть так:
Internazionale 1-1 Juventus
или FC Inter 1-1 Juventus
В будущем я хотел бы сделать запросы регулярных выражений чем-то вроде 'получить все результаты матчей Интер', чтобы не просматривать весь контент.
Итак, моя идея заключалась в том, чтобы сохранить для каждой команды их возможные имена (теги), а затем объединить их с помощью |.
Например: /(Inter|Internazionale|FC Inter)\s+\d+-\d+\d+(\w+)/s
Также я сомневаюсь в (\w+) для любого командного матча. Боюсь, что мне придется объединить все теги имен команд с | и пользуйся там. Для 30 команд и 2-3 тегов это будет огромное регулярное выражение.
Я ценю вашу помощь.
Это второе регулярное выражение должно было быть "/(Round\s+\d+)((?:(?!Round).)*)/s". Я пытался внести минимальные изменения, необходимые для соответствия регулярному выражению, но я должен был подумать и о захватах.
Что касается остальной части вашего вопроса, похоже, вы слишком много пытаетесь сделать с регулярными выражениями. Я бы просканировал всю страницу один раз, проанализировал ее и сохранил информацию в доступной для поиска структуре данных. Если вам нужна помощь с этим, вы должны начать новую беседу.
Это регулярное выражение найдет раунд 1, раунд 3, раунд 5 и т. д., Но не раунд 2, раунд 4, раунд 6 и т. д., Потому что заголовки четных раундов используются в совпадениях регулярных выражений нечетных раундов.