2015-12-27 6 views
1

Я пытаюсь проанализировать число, следующее «Обеденный:» в следующем тексте, под вторым уровнем. Поэтому «666» следует вернуть.Регулярное выражение для захвата текста с неизвестным числом повторных групп между

MAIN LEVEL 
     Entrance: 11 
     Dining: 33 

    SECOND LEVEL 
     Entrance: 4444 
     Living: 5555 
     Dining: 666 

    THIRD LEVEL 
     Dining: 999 
     Kitchen: 000 
     Family: 33332 

Если я использую что-то вроде (?:\bDining:\s)(.*\b) то захватывает первое вхождение под MAIN. Поэтому я пытаюсь указать SECOND LEVEL в регулярном выражении, за которым следует повторяющийся шаблон: новые строки, несколько пробелов, а затем текст, до Dining:. This demo иллюстрирует две проблемы, с которыми я сталкиваюсь. Регулярное выражение используется: (?:\bSECOND\sLEVEL(\n\s+.*)*Dining:)(.*\b)

  1. ошибка «Катастрофические возвратами» появляется до вы не удалите самую последнюю строку, содержащую Laundry: 1. Это вызвано слишком большим количеством матчей или чем-то еще?
  2. После того, как вы удалите эту строку, regex фиксирует только последний матч под номером OTHER LEVEL .. Возвращает «2» в отличие от матча SECOND LEVEL.

Иногда Dining: не существует под SECOND LEVEL и поэтому ничего не нужно возвращать.

Что такое регулярное выражение, которое будет записывать только номер Dining:, и если оно не существует, то ничего не возвращает? Прямо регулярное выражение предпочтительнее, без зацикливания на Java, если это возможно. Спасибо

+0

Мне интересно требование для «без кода Java.» Вы используете фреймворк или это просто ваши личные предпочтения? – markspace

+0

Хороший вопрос. Я просто стараюсь оставаться последовательным, так как много другого моего извлечения текста связано с регулярным выражением, поэтому я надеялся избежать использования циклов или чего-то еще для части процесса извлечения и чистого регулярного выражения для другого. Возможно, это глупо, хотя – Mathomatic

ответ

2

Используйте негативное выражение для регулярных выражений.

"(?m)^\\s*\\bSECOND LEVEL\\n(?:(?!\\n\\n)[\\s\\S])*\\bDining:\\s*(\\d+)" 

DEMO

+0

Это отлично работает, спасибо. Я прочитал объяснение, но я смущен тем, что говорит регулярное выражение.Это говорит: «Посмотрите вперед, чтобы две новые строки никогда не существовали последовательно (представляя изменение в УРОВНЯХ), а затем буквальный матч« Обеденный: «...» В любом случае, спасибо – Mathomatic

+0

ya, это гарантирует, что есть 't пустая строка, присутствующая между строками 'второго уровня' и' обеденными'. –

+0

О, да! Цените это. – Mathomatic

1

Лучший пример, который я знаю для катастрофических возвратов from here является (x+x+)+y. То есть он не может выработать правильные границы для групп захвата, содержащих x, потому что существует слишком много способов их разделения.

xxxxy - это первые два + один раз, третий в два раза или каждый первый и третий один раз, или один из первого трижды, другой один раз и последний раз. Как вы можете видеть, это становится опасным!

Вы были (?:\bSECOND\sLEVEL(\n\s+.*)*Dining:)(.*\b) ПРИМЕЧАНИЕ (\n\s+.*)* .* может быть кошмаром, когда в сочетании с предыдущим \n\s и огорожен *. Он должен быть переписан (\n\s+[^\s\n][^\n]*)*, что гарантирует, что каждый квантификатор заканчивается до начала следующего, сводя к минимуму обратный поиск.

С такого рода мышления в виду, я придумал следующее регулярное выражение, чтобы соответствовать вашей строки:

(?<=SECOND LEVEL\n)(?:\s+(?:[^\s\n:][^\n:]*):[^\n]*)*\s+Dining:\s*([^\s\n][^\n$]*) 
+0

Выглядит отлично! Спасибо. Я склонен пойти с другим ответом из-за его репутации и, казалось бы, более чистое/короткое регулярное выражение. Без сомнения, сейчас я собираюсь изучить ваше решение, хотя и понимаю. Спасибо, что нашли время. – Mathomatic

 Смежные вопросы

  • Нет связанных вопросов^_^