Скажите RegEx, чтобы игнорировать скобки в кавычках

У меня есть следующий RegEx, который используется и работает:

/\B@(@?\w+(?:::\w+)?)([ \t]*)(\( ( (?>[^()]+) | (?3) )* \))?/x

Где эта строка @extends('template', 'test') правильно группирует и дает мне то, что мне нужно.

Проблема в том, что если строка содержит незакрытые скобки внутри кавычек — это не удастся:

@extends('template', 'te)st') дает @extends('template', 'te) в качестве выхода

Как я могу сказать этому RegEx игнорировать круглые скобки, которые находятся внутри кавычек (либо ' или же ")

Вот демонстрация проблемы RegExr: http://regexr.com/v1?396ci

И вот список строк, которые все должны быть в состоянии передать:

@extends('template', 'test')     // working
@extends('template', $test)      // working
@extends('template', 'te()st')   // working
@extends('template', 'te)st')    // broken
@extends('template', 'te())st')  // broken
@extends('template', 'te(st')    // broken
@extends('template', 'test)')    // broken
@extends('template', '(test')    // broken

Я сузил это — и я думаю, что я должен быть в состоянии сказать

(
\(  <-- only if not inside quotes
(
(?>[^()]+) | (?3)
)*
\) <-- only if not inside quotes
)?

Но я не могу понять, как применить это правило к этим конкретным скобкам

5

Решение

Вы можете использовать Lookahead для этой цели

Вот мое регулярное выражение, которое будет соответствовать второму аргументу всех extends

(? = (\ Ш +) | \ ш + ()) [\ ш) (] +

Сломать:

' : Начать поиск строки с кавычки

?=XXX) : Позитивный взгляд вперед, обеспечивающий присутствие XXX впереди

(\w+\)|\w+\() : Поиск открывающих или закрывающих скобок

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

[\w\)\(]+ : Просто так

Теперь, когда мы можем найти кавычки с круглыми скобками внутри, мы можем использовать условие if-else, чтобы использовать соответствующие правила для каждого случая

(?(?=regex)then|else)

Вот как я это реализовал:

(?(?='(?=(\w+\)|\w+\())) <- condition, same as above
'[\w\)\(]+' <- We have a match so we ignore parenthesis
|'\w+' <- Here we don't
)

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

Вот мое регулярное выражение, которое соответствует всем вашим случаям.

\B@\w+\('[\w+\s]+',\s+(?(?='(?=(\w+\)|\w+\()))'[\w\)\(]+'|('\w+'|\$\w+))\)

Вы можете увидеть тестовые случаи Вот

PS. Чтобы показать, что это действительно работает, я добавил несколько неудачных тестов.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]