Подтвердить что ты не робот

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

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

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

X (Y) Z

Куда:

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

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

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

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

([0-9]+) +Z

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

4b9b3361

Ответ 1

(\d+)\s+(\(.*?\))?\s?Z

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

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

Ответ 2

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

^\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

Ответ 3

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

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

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

Ответ 4

Попробуйте следующее:

X (\(Y\))? Z

Ответ 5

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

$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