Соответствие необязательной подстроки в регулярном выражении
Я разрабатываю алгоритм для анализа числа из ряда коротких строк. Эти строки несколько регулярны, но есть несколько различных общих форм и несколько исключений. Я пытаюсь создать набор регулярных выражений, которые будут обрабатывать различные формы и исключения; Я буду применять их один за другим, чтобы посмотреть, получу ли я совпадение.
Одна из этих форм выглядит примерно так:
X (Y) Z
Куда:
-
X
- это число, которое я хочу захватить. -
Z
является статическим, предопределенным текстом. это в основном, как я определяю, применима ли эта конкретная форма или нет -
Y
- строка неизвестной длины и содержания, заключенная в круглые скобки.
Также: Y
необязательно; это не всегда появляется в строке с Z
и X
Итак, я хочу иметь возможность извлечь числа из всех этих строк:
-
10 Z
-
20 (foo) Z
-
30 (bar) Z
Прямо сейчас у меня есть регулярное выражение, которое захватит первое:
([0-9]+) +Z
Моя проблема в том, что я не знаю, как создать регулярное выражение, которое будет соответствовать серии символов, если и только если они заключены в круглые скобки. Может ли это быть сделано в одном регулярном выражении?
Ответы
Ответ 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