RegEx fallando desde PHP 7.4, trabajando en 7.3

Sep 10 2020

¿Alguna idea de por qué este preg_match funciona hasta PHP7.2 pero falla con 7.3+?

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

Advertencia: preg_match (): Error de compilación: carácter no reconocido después de (? O (? -

Salida de PHP 7.2 y anterior:

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

La expresión regular parece estar bien, ¿no?
https://regex101.com/r/LGdhaM/1

Respuestas

4 WiktorStribiżew Sep 10 2020 at 16:04

En PHP 7.3 y versiones posteriores, la extensión de Expresiones regulares compatibles con Perl (PCRE) se actualizó a PCRE2.

La documentación de sintaxis de PCRE2 no aparece (?X)como una opción de modificación en línea disponible. Estas son las opciones admitidas:

  (?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

Sin embargo, en realidad puede usar la Xbandera después del delimitador final:

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

Vea la demostración de PHP 7.4 .

Para cancelar el (?U)efecto, puede usar cualquiera de las dos opciones: un (?-U)modificador en línea, como en

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

O incluya los patrones afectados en un (?U:...)grupo de modificadores:

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

Vea más sobre los cambios en el manejo de expresiones regulares en PHP 7.3+ en preg_match (): Error de compilación: rango no válido en la clase de caracteres en el desplazamiento .