2016-07-18 1 views
1

Я хочу получить аргументы функции строки.Регулярное выражение для аргументов функции анализа с функциями

sample(5*5) euros 

Это правильно работает с:

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

Demo here.

Проблема заключается в том, когда я ставлю другую функцию внутри аргумента:

sample(decimal(5*5)) euros 

С только функции это работает с:

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

Demo here.

Но с двумя функциями или больше я не могу получить аргументы функции:

sample(decimal(5*5)) toString(euros) 

Как я могу получить аргументы функции с регулярным выражением ?.

+1

Что такое regex flavor (библиотека регулярных выражений, язык программирования, инструмент)? Проверьте ['([^ \ s)] +) (\ (((>> [^()] ++ | (? 1)) *) \))'] (https://regex101.com/r/qE2fR9/2), но если вы создаете парсер, я думаю, вам не нужно регулярное выражение. –

+0

Я делаю парсер с PHP: 'preg_match ('/ ([^ \ s \)] +) \ ((. +) \) /', 'Sample (десятичный (5 * 5)) toString (euros)' , $ matches) ' –

+1

Я уверен, что @Wiktor может дать вам умное регулярное выражение для этого, но если вы действительно ожидаете вложенных вызовов функций на произвольную глубину, вам следует рассмотреть возможность использования синтаксического анализатора. –

ответ

1

Если вы пишете анализатор вы можете обойтись без регулярных выражений. С образовательной точки зрения, в PHP PCRE regex, вы можете использовать рекурсию и подпрограммы вызовов.

Посмотрите

(?<name>[^\s()]+)(\((?<body>(?>[^()]++|(?2))*)\)) 

Смотрите «Имя» regex demo

Группа будет содержать имя функции и группы «тело» будет держать то, что находится внутри согласующих скобок.

Примечание вам нужно добавить как ( и ) к инверсный символьного класса(?<funcion>[^\s()]+), потому что в случае, если у вас есть sample(decimal(3*3)) эта группа будет захватывать подстроку до ) (sample(decimal). Таким образом, вам необходимо исключить как (, так и ).

(\((?<body>(?>[^()]++|(?2))*)\)) часть представляет собой группу захвата (с ID = 2), которые могут быть Рекурсия (т.е. «повторного», «расширенный» много раз) с вызовом подпрограммы (?2).

Это соответствует

  • \( - открытый круглый кронштейн
  • (?<body>(?>[^()]++|(?2))*) - Группа "тело", что соответствует нулю или более последовательностей:
    • [^()]++ - 1+ символов, отличных от ( и ) или
    • (?2) - все \((?<body>(?>[^()]++|(?2))*)\) подшаблон
  • \) - закрывающая скобка

(?2)вызова подпрограммы необходимость (по сравнению с рекурсии с (?R)) продиктовано тем, что нам нужно повторить/рекурсию части рисунка ,

Поскольку группа 2 является «технической» группой захвата, может быть хорошей идеей использовать именованные группы захвата для тех частей, которые мы хотим использовать.

+0

Исправлено - '(? 1)'> '(? 2)', зафиксированное везде в ответе. –

+0

Теперь отлично !. Огромное спасибо. Это очень простой парсер с четырьмя функциями. Спасибо, что объяснили это. –

+0

Возможно ли это с помощью 'sample (десятичный (5 * 5))'? Без пробелов не работает. [Проверить] (https://regex101.com/r/qE2fR9/6) –

1

Используйте внешний вид, который определяет следующий символ скобки (если есть), открыть, а также использовать квантификатор refucant.

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

([^\s\)]+)\((.+?)\)(?=[^()]*(\(|$)) 
Смежные вопросы