告诉RegEx在引号内忽略括号

时间:2017-05-15 00:46:50

标签: php regex regex-group

我使用以下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  
)?

但我似乎无法弄清楚如何将该规则应用于这些特定的括号

1 个答案:

答案 0 :(得分:3)

您可以将lookahead用于此目的

这里的正则表达式与所有extends的第二个参数相匹配

  

(=(\ W +)|?\ W +())[\ w)的(] +

故障:

  

':开始搜索带引号的字符串

     

?=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
)

PS。我不理解你为你的正则表达式中的其他部分所写的很多内容,也许是为了涵盖其他一些情况,所以我没有写到修改你的原始正则表达式。您可以使用上面提到的那个来简单地检查第二个参数

这是我的正则表达式,与你的所有情况相符。

  

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

您可以看到测试用例here

PS。为了表明它确实有效,我添加了一些失败的测试用例