RegEx falhando desde PHP 7.4, funcionando em 7.3

Sep 10 2020

Alguma idéia de por que este preg_match funciona até PHP7.2, mas falha com 7.3+?

$word = 'umweltfreundilch'; //real life example :/ preg_match('/^(?U)(.*(?:[aeiouyäöü])(?:[^aeiouyäöü]))(?X)(.*)$/u', $word, $matches);
var_dump($matches);

Aviso: preg_match (): Falha na compilação: caractere não reconhecido após (? Ou (? -

Resultado do PHP 7.2 e abaixo:

array(3) {
  [0]=>
  string(16) "umweltfreundilch"
  [1]=>
  string(2) "um"
  [2]=>
  string(14) "weltfreundilch"
}

RegEx parece estar bem, não é?
https://regex101.com/r/LGdhaM/1

Respostas

4 WiktorStribiżew Sep 10 2020 at 16:04

No PHP 7.3 e posterior, a extensão Perl-Compatible Regular Expressions (PCRE) foi atualizada para PCRE2.

A documentação da sintaxe PCRE2 não é listada(?X) como uma opção de modificador embutido disponível. Aqui estão as opções com suporte:

  (?i)            caseless
  (?J)            allow duplicate named groups
  (?m)            multiline
  (?n)            no auto capture
  (?s)            single line (dotall)
  (?U)            default ungreedy (lazy)
  (?x)            extended: ignore white space except in classes
  (?xx)           as (?x) but also ignore space and tab in classes
  (?-...)         unset option(s)
  (?^)            unset imnsx options

No entanto, você pode realmente usar o Xsinalizador após o delimitador final:

preg_match('/^(?U)(.*[aeiouyäöü][^aeiouyäöü])(.*)$/Xu', $word, $matches)

Veja a demonstração do PHP 7.4 .

Para cancelar o (?U)efeito, você pode usar uma das duas opções: um (?-U)modificador embutido, como em

preg_match('/^(?U)(.*[aeiouyäöü][^aeiouyäöü])(?-U)(.*)$/u', $word, $matches);
//                                           ^^^^^

Ou coloque os padrões afetados em um (?U:...)grupo de modificadores:

preg_match('/^(?U:(.*[aeiouyäöü][^aeiouyäöü]))(.*)$/u', $word, $matches);
//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        

Veja mais sobre as mudanças na manipulação de regex no PHP 7.3+ em preg_match (): Falha na compilação: intervalo inválido na classe de caractere no deslocamento .