当引号内出现括号时,告诉正则表达式忽略括号。

5
我有以下已使用并起作用的正则表达式:
/\B@(@?\w+(?:::\w+)?)([ \t]*)(\( ( (?>[^()]+) | (?3) )* \))?/x
其中这个字符串 @extends('template', 'test') 正确地分组并给出了我需要的内容。
问题是,如果字符串中包含引号内未关闭的括号,则会失败:
@extends('template', 'te)st') 将输出 @extends('template', 'te)
如何告诉这个正则表达式忽略在引号内的括号(单引号或双引号)?
这里是一个演示该问题的 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个回答

4

您可以使用前瞻来实现这个目的

以下是我的正则表达式,它将匹配所有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
)

注:我并没有完全理解你在正则表达式的其他部分所写的内容,可能是为了覆盖其他情况,因此我不会修改您原始的正则表达式。您只需使用上述提到的第二个参数检查替换即可。

以下是我的正则表达式,它可以匹配所有您的情况。

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

您可以在这里看到测试用例。

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


谢谢@Mayank - 这很接近了 - 但是你的测试用例没有包括最后的 ) - Laurence
附注:我添加了一个额外的测试用例,这是我在原始问题中忘记包含的。 - Laurence

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接