preg_replace_callback preg_replace preg_match online especiales ejemplos caracteres php regex wordpress preg-replace

php - preg_match - Advertencia: preg_replace(): modificador desconocido '']''



preg_replace_callback (2)

Otros ejemplos

La share ya explica el motivo de las advertencias de "Modificador desconocido". Esto es solo una comparación de otras variantes típicas.

  • Cuando se olvida de agregar expresiones regulares / delimitadores / , se supone que el primer símbolo que no es una letra es uno. Por lo tanto, la advertencia suele ser sobre lo que sigue a un símbolo de agrupación (…) , […] meta:

    preg_match("[a-zA-Z]+:/s*.$" ↑ ↑⬆

  • En ocasiones, su expresión regular ya utiliza un delimitador personalizado ( : aquí), pero aún contiene el mismo carácter que el literal no escindido. Entonces se confunde como delimitador prematuro. Por eso, el siguiente símbolo recibe el trofeo "Modificador desconocido ❌".

    preg_match(":/[[/d:/]+/]:" ↑ ⬆ ↑

  • Cuando uses el clásico / delimitador, ten cuidado de no tenerlo dentro de la expresión regular, literalmente. Esto ocurre con mayor frecuencia al intentar hacer coincidir los nombres de archivos no escaneados :

    preg_match("/pathname/filename/i" ↑ ⬆ ↑

    O cuando se combinan tags estilo de ángulo / corchete cuadrado:

    preg_match("/<%tmpl:id>(.*)</%tmpl:id>/Ui" ↑ ⬆ ↑

  • Los patrones regex de estilo de plantilla (Smarty o BBCode) a menudo requieren {…} o […] corchetes. Ambos deberían ser escapados. (Sin embargo, un {} par más externo es la excepción).

    También se malinterpretan como delimitadores emparejados cuando no se usa un delimitador real. Si también se usan como carácter literal dentro, entonces eso es, por supuesto ... un error.

    preg_match("{bold[^}]+}" ↑ ⬆ ↑

  • Siempre que la advertencia diga " Delimitador no debe ser alfanumérico o barra invertida ", también olvidó por completo los delimitadores:

    preg_match("ab?c*" ↑

  • " El modificador desconocido ''g'' " a menudo indica una expresión regular que se copió textualmente de JavaScript o Perl.

    preg_match("/abc+/g" ⬆

    PHP no usa el indicador global /g . En su lugar, la función preg_replace funciona en todas las ocurrencias, y preg_match_all es la preg_match_all búsqueda "global" para el preg_match una ocurrencia.

    Por lo tanto, solo elimina la bandera /g .

    Ver también:
    · Advertencia: preg_replace (): modificador desconocido ''g''
    · Preg_replace: bad regex == ''Desconocido Modificador''?

  • Un caso más peculiar pertenece a la bandera PCRE_EXTENDED /x . Esto es a menudo (o debería ser) utilizado para hacer que las expresiones regulares sean más nobles y legibles.

    Esto permite usar # comentarios en línea. PHP implementa los delimitadores de expresiones regulares encima de PCRE. Pero no trata # de ninguna manera especial. Que es cómo un delimitador literal en un # comentario puede convertirse en un error:

    preg_match("/ ab?c+ # Comment with / slash in between /x"

    (También cabe destacar que el uso de # como #abc+#x delimitador puede ser doblemente desaconsejable).

  • La interpolación de variables en una expresión regular requiere que sean pre escapadas o que sean expresiones regulares válidas. No puedes decir de antemano si esto va a funcionar:

    preg_match("/id=$var;/" ↑ ↺ ↑

    Lo mejor es aplicar $var = preg_quote($var, "/") en dichos casos.

    Ver también:
    · Modificador desconocido ''/'' en ...? ¿Qué es?

    Otra alternativa es usar /Q…/E escapes para cadenas literales sin comillas:

    preg_match("/id=/Q{$var}/E;/mix");

    Tenga en cuenta que esto es simplemente un atajo conveniente, no confiable / seguro. Se desmoronaría en caso de que $var contuviera un literal ''/E'' sí mismo (aunque fuera poco probable).

  • El modificador / e obsoleto es un problema completamente diferente. Esto no tiene nada que ver con los delimitadores, pero el modo de interpretación de la expresión implícita se está eliminando. Ver también: reemplazar preg_replace / e obsoleto con preg_replace_callback

Deléteres regex alternativos

Como se mencionó anteriormente, la solución más rápida a este error es simplemente elegir un delimitador distinto. Se puede usar cualquier símbolo que no sea una letra. Visualmente distintivos a menudo se prefieren:

  • ~abc+~
  • !abc+!
  • @abc+@
  • #abc+#
  • =abc+=
  • %abc+%

Técnicamente, podrías usar $abc$ o |abc| para delimitadores Sin embargo, es mejor evitar los símbolos que sirven como metacaracteres regex.

El hash # como delimitador también es bastante popular. Pero se debe tener cuidado en combinación con el modificador de legibilidad x / PCRE_EXTENDED . No puede usar comentarios # inline o (?#…) porque se confundirían como delimitadores.

Delimitadores de solo cita

Ocasionalmente, puede ver " y '' utilizados como delimitadores de expresiones regulares emparejados con su conternidad como el recinto de cadenas PHP:

preg_match("''abc+''" preg_match(''"abc+"''

Lo cual es perfectamente válido en lo que respecta a PHP. A veces es conveniente y discreto, pero no siempre legible en IDEs y editores.

Delimitadores vinculados

Una variación interesante son los delimitadores emparejados. En lugar de usar el mismo símbolo en ambos extremos de una expresión regular, puede usar cualquier combinación de <...> (...) [...] {...} paréntesis / paréntesis.

preg_match("(abc+)" # just delimiters here, not a capture group

Si bien la mayoría de ellos también sirven como metacaracteres de expresiones regulares, a menudo puede usarlos sin mayor esfuerzo. Siempre que esos paréntesis / paréntesis específicos dentro de la expresión regular estén emparejados o escapen correctamente, estas variantes son bastante legibles.

Delicadores regex de lujo

Un truco un tanto vago (que no está respaldado en este documento) es el uso de caracteres ASCII no imprimibles como delimitadores. Esto funciona fácilmente en PHP utilizando comillas dobles para la cadena de expresiones regulares y escapes octales para delimitadores:

preg_match("/001 abc+ /001mix"

El /001 es solo un personaje de control que no suele ser necesario. Por lo tanto, es muy poco probable que aparezca dentro de la mayoría de los patrones de expresiones regulares. Lo que lo hace adecuado aquí, aunque no muy legible.

Lamentablemente, no puede usar glicogramas Unicode como delimitadores. PHP solo permite caracteres de un solo byte. ¿Y por qué es eso? Bueno, me alegro de que hayas preguntado:

Delimitadores de PHP encima de PCRE

Las funciones preg_* utilizan el motor de preg_* regulares PCRE , que a sí mismo no le importa ni proporciona delimitadores. Para la semejanza con Perl, las funciones preg_* las implementan. Lo cual también es la razón por la que puede usar letras modificadoras /ism lugar de solo constantes como parámetro .

Consulte ext/pcre/php_pcre.c sobre cómo se preprocesa la cadena de ext/pcre/php_pcre.c regulares:

  • En primer lugar, se ignora todo el espacio en blanco inicial.

  • Cualquier símbolo no alfanumérico se toma como delimitador presunto. Tenga en cuenta que PHP solo respeta los caracteres de un solo byte:

    delimiter = *p++; if (isalnum((int)*(unsigned char *)&delimiter) || delimiter == ''//') { php_error_docref(NULL,E_WARNING, "Delimiter must not…"); return NULL; }

  • El resto de la cadena de expresiones regulares se recorre de izquierda a derecha. Solo se ignoran los símbolos de barra invertida // -campanada.

  • Si el delimitador se encuentra de nuevo, se comprueba que el resto solo contiene letras modificadoras.

  • Si el delimitador es uno de los ([{< )]}> )]}> paréntesis / brackets compatibles, entonces la lógica de procesamiento es más elaborada.

    int brackets = 1; /* brackets nesting level */ while (*pp != 0) { if (*pp == ''//' && pp[1] != 0) pp++; else if (*pp == end_delimiter && --brackets <= 0) break; else if (*pp == start_delimiter) brackets++; pp++; }

    Busca el delimitador izquierdo y derecho emparejado correctamente, pero ignora otros tipos de brackets / corchetes al contar.

  • La cadena de expresiones regulares sin formato se pasa al servidor PCRE solo después de que se hayan cortado los indicadores de delimitador y modificador.

Ahora todo esto es algo irrelevante. Pero explica de dónde provienen las advertencias del delimitador. Y todo este procedimiento es todo para tener un mínimo de compatibilidad Perl. Por supuesto, hay algunas desviaciones menores, como el contexto […] clase de caracteres que no recibe un tratamiento especial en PHP.

Más referencias

Tengo el siguiente error:

Advertencia: preg_replace (): modificador desconocido '']'' en xxx.php en la línea 38

Este es el código en la línea 38:

<?php echo str_replace("</ul></div>", "", preg_replace("<div[^>]*><ul[^>]*>", "", wp_nav_menu(array(''theme_location'' => ''nav'', ''echo'' => false)) )); ?>

¿Puede alguien ayudarme a solucionar este problema?


Por qué ocurre el error

En PHP, una expresión regular debe estar dentro de un par de delimiters . Un delimitador puede ser cualquier carácter no alfanumérico, no de barra invertida, no de espacio en blanco; / , # , ~ son los más utilizados. Tenga en cuenta que también es posible usar delimitadores de estilos de corchetes donde los corchetes de apertura y cierre son los delimitadores inicial y final, es decir, <pattern_goes_here> , [pattern_goes_here] etc. son todos válidos.

El error " Modificador desconocido X " suele aparecer en los dos casos siguientes:

  • Cuando su expresión regular carece de delimitadores .

  • Cuando usa el delimitador dentro del patrón sin escapar de él.

En este caso, la expresión regular es <div[^>]*><ul[^>]*> . El motor de expresiones regulares considera todo desde < como el patrón de expresiones regulares, y todo después como modificadores.

Regex: <div[^> ]*><ul[^>]*> │ │ │ │ └──┬──┘ └────┬─────┘ pattern modifiers

] aquí hay un modificador desconocido, porque aparece después del delimitador de cierre > . Por eso PHP arroja ese error.

Dependiendo del patrón, el reclamo de modificador desconocido podría haber sido sobre * , + , p , / o ) o casi cualquier otra letra / símbolo. Solo imsxeADSUXJu son modificadores PCRE válidos .

Como arreglarlo

La solución es fácil. Simplemente ajuste su patrón de expresiones regulares con cualquier delimitador válido. En este caso, podría elegir ~ y obtener lo siguiente:

~<div[^>]*><ul[^>]*>~ │ │ │ └─ ending delimiter └───────────────────── starting delimiter

Si recibe este error a pesar de haber usado un delimitador, puede deberse a que el propio patrón contiene apariciones no guardadas de dicho delimitador.

O delimitadores de escape

/foo[^/]+bar/i ciertamente lanzaría un error. Para que pueda escapar usando una / barra invertida si aparece en cualquier parte dentro de la expresión regular:

/foo[^//]+bar/i │ │ │ └──────┼─────┴─ actual delimiters └─────── escaped slash(/) character

Este es un trabajo tedioso si su patrón de expresiones regulares contiene tantas ocurrencias del carácter delimitador.

La forma más limpia, por supuesto, sería usar un delimitador diferente por completo. Idealmente, un personaje que no aparece en ningún lugar dentro del patrón de #foo[^/]+bar#i regulares, digamos # - #foo[^/]+bar#i .

Más lectura: