Соответствие необязательной подстроке в регулярном выражении - PullRequest
37 голосов
/ 27 октября 2008

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

Одна из этих форм выглядит примерно так:

X (Y) Z

Где:

  • X - это число, которое я хочу захватить.
  • Z - это статический, предопределенный текст. это в основном то, как я определяю, применима ли данная форма или нет.
  • Y - строка неизвестной длины и содержания, заключенная в круглые скобки.

Также: Y необязательно; он не всегда появляется в строке с Z и X. Итак, я хочу иметь возможность извлечь числа из всех этих строк:

  • 10 Z
  • 20 (foo) Z
  • 30 (bar) Z

Прямо сейчас у меня есть регулярное выражение, которое захватит первое:

([0-9]+) +Z

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

Ответы [ 5 ]

50 голосов
/ 27 октября 2008
(\d+)\s+(\(.*?\))?\s?Z

Обратите внимание на экранированные скобки и квантификаторы ? (ноль или один раз). Любая группа, которую вы не хотите захватывать, может быть (?: группы без записи).

Я согласен с пробелами. \s лучший вариант там. Я также изменил квантификатор, чтобы в начале были цифры. Что касается перевода строки, это будет зависеть от контекста: если файл анализируется построчно, это не будет проблемой. Другой вариант - привязать начало и конец строки (добавьте ^ в начале и $ в конце).

17 голосов
/ 27 октября 2008

Это должно сработать:

^\d+\s?(\([^\)]+\)\s?)?Z$

Не проверял, хотя, но позвольте мне дать вам разбивку, так что если есть какие-либо ошибки, они должны быть довольно просто найти:

Первое начало:

^ = beginning of string
\d+ = one or more decimal characters
\s? = one optional whitespace

Тогда эта часть:

(\([^\)]+\)\s?)?

На самом деле:

(.............)?

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

\([^\)]+\)\s?

\( = an opening bracket
[^\)]+ = a series of at least one character that is not a closing bracket
\) = followed by a closing bracket
\s? = followed by one optional whitespace

И конец состоит из

Z$

Где

Z = your constant string
$ = the end of the string
7 голосов
/ 27 октября 2008

Вы можете сделать это:

([0-9]+) (\([^)]+\))? Z

Однако это не будет работать с вложенными паренями для Y. Вложение требует рекурсии, которая больше не является строго регулярной (но не зависит от контекста). Современные движки регулярных выражений все еще могут справиться с этим, хотя и с некоторыми трудностями (обратные ссылки).

4 голосов
/ 27 октября 2008

Попробуйте это:

X (\(Y\))? Z
0 голосов
/ 13 июля 2018

Если все, что вам нужно для захвата, это число, а число появляется в начале строки, то вы можете просто использовать Жонглирование PHP-типа , чтобы выполнить эту тяжелую работу очень быстро и чрезвычайно эффективно: 1003 *

$value = "10 Z";
$value = "20 (foo) Z";
$value = "30 (bar) Z";
$value = "Cheese";
$value = "   40 (flat) Z";
$value = "22(456)";

$X = (int)trim($value); 

Выходы:

$ х = 10
$ х = 20
$ х = 30
$ x = 0
$ х = 40
$ х = 22 * ​​1014 *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...