Маленькая помощь с регулярным выражением - PullRequest
0 голосов
/ 01 сентября 2011

как я могу сопоставить это:

(1, 'asd', 'asd2')

но не соответствует этому:

(1, '(data)', 0)

Я хочу сопоставить (и), но не сопоставить (и) внутри (и).

На самом деле это запросы, и я хочу разделить их с помощью preg_split.

/[\(*\)]+/

разбивает их, но также разбивает (и) внутри них, как я могу это исправить?

Пример:

Данные:

(1, 'user1', 1, 0, 0, 0) (2, 'user (2)', 1, 0, 0, 1)

Я хочу разделить их на:

Array(
    0 => (1, 'user1', 1, 0, 0, 0)
    1 => (2, 'user(2)', 1, 0, 0, 1)
);

вместо него его делится на:

Array(
    0 => (1, 'user1', 1, 0, 0, 0)
    1 => (2, 'user
    2 => 2
    3 => ', 1, 0, 0, 1)
);

Ответы [ 3 ]

3 голосов
/ 01 сентября 2011

Вы не можете использовать preg_split для этого (поскольку вы не соответствуете границам, но более длинным образцам). Но это может быть возможно с preg_match_all:

 preg_match_all(':\( ((?R) | .)*? \):x', $source, $matches);
 print_r($matches[0]);

Вместо ?R рекурсивной версии вы также можете просто подготовить шаблон для одного уровня внутренних скобок. Но на самом деле это не выглядело бы намного проще.

 :\( ( [^()]* | \( [^()]* \) )+ \):x
3 голосов
/ 01 сентября 2011

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

  • Если это ), разделите там.(Я предполагаю, что скобки сбалансированы в строке и не могут быть вложенными)
  • Если это ', игнорируйте любые ) до закрытия ' (если его можно избежать,вы можете посмотреть на предыдущие символы для нечетного числа \).

Я думаю, что это более простое решение, чем регулярное выражение.

2 голосов
/ 01 сентября 2011

Ваша грамматика выглядит как

list:  '(' num ( ',' term )(s?) ')'
term:  num | str
num:   /[0-9]+/
str:   /'[^']*'/

Итак, шаблон

/ \G \s* \( \s* [0-9]+ (?: \s* , \s* (?: [0-9]+ | '[^']*' ) )* \s* \) /x

Ну, это просто для соответствия.Извлечение является хитрым, если PHP работает как Perl.Если вы хотите сделать с соответствием регулярному выражению, вы должны сделать это в два прохода.

Сначала вы извлекаете список:

/ \G \s* \( \s* ( [0-9]+ (?: \s* , \s* (?: [0-9]+ | '[^']*' ) )* ) \s* \) /x

Затем вы извлекаете термины из списка:

/ \G \s* ( [0-9]+ | '[^']*' ) (?: \s* , )? /x
...