警告:preg_match():编译失败:(?或(?-)后面的字符无法识别


Warning: preg_match(): Compilation failed: unrecognized character after (? or (?-

我有一个由以前的程序员编写的代码,一个regex preg_match引发编译错误:

$regex_t = "/" . $op . "(?''>[^" . $op . $cl . "]+)*" . $cl . "/s";
preg_match($regex_t, $text, $inner);

我收到的警告是:

警告:preg_match():编译失败:无法识别的字符在(?或(?-偏移4 之后

此外,我想提到的是,在var_dump($regex_t),值为:

string '/'{(?'>[^'{'}]+)*'}/s' (length=21)

由于一个奇怪的原因,程序员逃离了>(这是永远不需要的)

只有这些字符需要转义才能获得文字字符(在字符类之外):

( ) ^ $ [ ' | . * + ?
{   # only in these cases: {n} {m,n} {m,}
    # where m and n are integers

+图案分隔符

大多数情况下,正则表达式引擎会简单地忽略不需要转义的转义字符(或者像'b 'w 'd…这样没有特殊含义的转义字符)。但这里的情况并非如此,因为(?>是打开原子组的固定序列,并且除了以下情况之外,不允许使用(?序列:

  • 非捕获组:(?:...)
  • 原子团:(?>...)
  • 内联修饰符:(?i) (?-i)
  • 具有内联修饰符的非捕获组:(?i:...)(?-i:...)
  • 环视:(?=...) (?!...) (?<=...) (?<!...)
  • 一个分支复位组:(?|...|...)
  • 条件测试:(?(condition)...|...)
  • 对子模式的引用:(?1) (?-1) (?R)
  • 定义组:(?(DEFINE)...)
  • 命名子模式:(?<John>...) (?P<John>...) (?'John'...)
  • 对命名子模式的引用:(?&John) (?P>John)

所以(?'没有被识别为这些序列之一,这就是为什么你会得到一个错误。

也许程序员想写一个原子组(?>...)(可能是这样,因为由于组是重复的,如果下面的子模式失败,使用原子组可以减少回溯),或者像Avinash建议的那样,忘记了非捕获组(?:'':,但要获得一个字面反斜杠,您需要在一个双引号字符串中使用四个反斜杠。