Проблема с пробелами в RegEx с группами захвата - PullRequest
4 голосов
/ 19 марта 2011

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

Обновление : «Текст» может быть практически любым символом, поэтому изначально у меня было .*. Важно отметить, что он также может содержать пробелы.

  1. Текст
  2. Текст 01
  3. Текст 01 от 03
  4. Текст 01 (из 03)
  5. Текст 01-03

Я хотел бы захватить «Текст», «01» и «03» как отдельные группы, и все, кроме «Текст», являются необязательными. Лучшее, что я смог сделать, это:

\s*(.*)\s+(\d+)\s*(?:\s*\(?\s*(?:of|-)\s*(\d+)\s*\)?\s*)

Это соответствует # 3- # 5 и помещает их в соответствующие группы захвата. Однако я не могу понять, почему, когда я добавляю дополнительный ? в конец, чтобы сделать часть выражения после 01 необязательной, мои группы захвата становятся все более прикольными.

\s*(.*)\s+(\d+)\s*(?:\s*\(?\s*(?:of|-)\s*(\d+)\s*\)?\s*)?

RegEx выше соответствует # 2- # 5, но группы захвата верны только для # 2 и # 5.

Это похоже на прямое регулярное выражение, поэтому я не знаю, почему у меня так много проблем с ним.

Это ссылка на онлайн-оценщик RegEx, который я использую для отладки: http://regexr.com? 2tb64 . Ссылка уже содержит первый RegEx и заполненные тестовые данные.

Ответы [ 3 ]

6 голосов
/ 19 марта 2011

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

var re = /^\s*(.+?)(?:\s+(\d+)(?:(?:\s+\(?of\s+|-)(\d+)\)?)?)?$/i;

Чтобы это работало в вашем инструменте Regexr, обязательно включите «многострочный параметр».

Здесь то же самое в PHPсинтаксис (с множеством сочных комментариев!):

$re = '/ # Always write non-trivial regex in free-space mode!
    ^                  # Anchor to start of string.
    \s*                # optional leading whitspace is ok.
    (.+?)              # Text can be pretty much anything.
    (?:                # Group to allow applying ? quantifier
      \s+              # WS separates "Text" from first number.
      (\d+)            # First number.
      (?:              # Group to allow applying ? quantifier
        (?:            # Second number prefix alternatives
          \s+\(?of\s+  # Either " of 03" and " (of 03)",
        | -            # or just a dash  for "-03" case.
        )              # End second number prefix alternatives
        (\d+)          # Second number
        \)?            # Match ")" for " (of 03)" case.
      )?               # Second number is optional.
    )?                 # First numebr is optional.
    $                  # Anchor to start of string.
    /ix';
1 голос
/ 19 марта 2011

Ваш второй близок

Итак, я переделал: regexr , теперь все совпадения в правильных группах.

\s*(\w*)\s+(?:\s*(\d+)\s*(?:\s*\(?\s*(?:of|-)\s*(\d+)\s*\)?)?)?
0 голосов
/ 19 марта 2011

Попробуйте это:
http://regexr.com? 2tb67

Regex выглядит примерно так:

(\w+?)\s+(\d*)[^\d]*(\d+)

Соответствует всем буквам, за которыми следуют любые пробелы,затем сопоставьте все цифры, затем все, что не является цифрами, затем сопоставьте оставшиеся цифры.

Обратите внимание, что второй результат, вероятно, не идеален для вас, поскольку 01 входит в совпадение третьей группы.Но это соответствует всем вашим случаям.

...