Si no sabes hacer redirecciones con expresiones regulares en tu sitio WordPress, aunque uses el plugin Redirection, no te preocupes, no estás solo, es algo que se le atasca a cualquiera, por años que lleve en el desarrollo de webs.
Entre que hay varias maneras de hacer redirecciones mediante expresiones regulares, y que no es algo que se haga todos los días, cuando necesitas crear una redirección REGEX o mediante expresiones regulares, puede pasar de todo menos lo que esperabas, sobre todo si te limitas a copiar y pegar ejemplos de redirecciones mediante expresiones regulares que encuentres por ahí, incluso aquí.
Si no comprendes bien las redirecciones mediante expresiones regulares es más fácil que consigas un bucle infinito en tu web que lo que sea que esperases conseguir.
Por este motivo, mi objetivo hoy es ayudarte a comprender bien, y de manera lo más sencilla posible, qué son las expresiones regulares, qué puedes hacer con ellas, y sobre todo cómo hacerlas correctamente, para crear potentes redirecciones, y que funcionen.
Qué son las expresiones regulares
Por lo general, una expresión regular es un grupo o conjunto de distintos caracteres que se utilizan para encontrar un patrón determinado dentro de un fragmento de texto. No son algo nuevo, sino que se llevan utilizando desde mediados del siglo pasado.
Lo primero que debes entender es que no son parte de ningún lenguaje de programación existente, sino que son en sí mismas una especie de nuevo lenguaje de programación, con sus propios parámetros y reglas, e incluso hay editores especializados en registrar, analizar y probar expresiones regulares, como regex101, totalmente online.
Cuando hablamos de redirecciones, una coincidencia de URL simple coincidirá siempre exactamente con una URL. Por el contrario, una URL de expresión regular puede coincidir con muchas URLs. Además de hacer coincidir muchas URLs, una expresión regular puede extraer información de la URL de origen y copiarla en la URL de destino.
Para que entiendas de lo que estoy hablando…
Una redirección «normal», que tenga la URL de origen /mi-url
solo coincidirá con las solicitudes de /mi-url
.
Una redirección que tenga la URL de origen /mi-url/.*
coincidirá con las solicitudes de:
/mi-url/algo /mi-url/otro-algo … etc.
La parte importante de /mi-url/.*
en lo que se refiere a expresiones regulares es .*
. Esta es la parte de expresión regular de la URL y equivale a decir «algo que coincida con /mi-url/
seguido de cualquier secuencia de caracteres».
¿Ahora mejor?
Sintaxis de las expresiones regulares (cómo se escriben, vaya)
La parte más dura de las expresiones regulares es comprender la sintaxis. Todo el que ve ve expresiones regulares por primera vez se pregunta:
¿¡Qué son todos estos símbolos extraños y qué significan!?
Este es, de lejos, el mayor obstáculo al principio, y por eso voy a explicarlo de la manera más sencilla y detallada posible.
Delimitadores
El primer elemento de una expresión regular son los delimitadores. Estos son los límites de sus expresiones regulares. El delimitador más común que verás en las expresiones regulares es la barra diagonal ( /
).
Dicho esto, hay más de un tipo de delimitador que puedes usar. Depende de la sintaxis que utilice tu lenguaje de programación. Por ejemplo, PCRE (la sintaxis que usa PHP) también admite los siguientes delimitadores:
- Hashtag (
#
) - Porcentaje (
%
) - Signo más (
+
) - Virgulilla (
~
)
También puedes usar corchetes (como ()
, {}
, []
y <>
) como delimitadores, pero no es algo que verás muy a menudo o incluso puede que no lo veas nunca. Sólo los veremos para que tengas una guía completa.
¿Por qué utilizar distingos delimitadores?
Todos estos delimitadores pueden parecer un poco excesivos (y de hecho lo son), entonces, ¿por qué querrías utilizar delimitadores diferentes?
La razón principal para utilizar un delimitador diferente es la legibilidad.
Si tu expresión regular contiene muchas barras, no tendrá que escaparlas. Por ejemplo, digamos que quieres probar si una solicitud utiliza HTTPS . Tu expresión regular con el delimitador por defecto sería /https:\/\//
. Como puedes ver, esto es difícil de leer ya que tenemos que escapar de cada barra usando una barra invertida.
Pero podemos solucionar este problema cambiando a otro delimitador, como el signo de porcentaje. Si hacemos eso, nuestra expresión regular se convierte en %https://%
. ¡Y eso es mucho más fácil de leer!
Patrón, átomos y metacaracteres
Dentro de nuestros delimitadores, tenemos el patrón que queremos que busque nuestra expresión regular. Este patrón está formado por lo que llamamos átomos. Un átomo puede ser un literal de caracteres o un metacarácter .
Los metacaracteres son, con diferencia, la parte más confusa de las expresiones regulares. Son caracteres que tienen un significado especial cuando se usan en expresiones regulares. Dicho esto, comprender el significado de estos metacaracteres también es muy importante.
De hecho, es la esencia de aprender a utilizar expresiones regulares. Una expresión regular sin metacaracteres ni siquiera es una expresión regular. Es simplemente una cadena literal (también conocida como simplemente una cadena) como cualquier otra.
Por eso tendrás que aprender el significado de estos metacaracteres. La mayoría de los procesadores de expresiones regulares admiten al menos catorce metacaracteres. Estos metacaracteres comunes son {}[]()^$.|*+?\
.
Definir el significado de los metacaracteres
Muy bien, ahora sabes lo importantes que son los metacaracteres para las expresiones regulares. El siguiente paso es repasar sus significados. Estos significados se dividen en cuatro grandes grupos: escape, agrupación, coincidencia de literal de caracteres y cuantificadores.
Escapando
El primer significado que veremos es escapar. La barra invertida ( \
) es el carácter de escape utilizado por las expresiones regulares. Vimos un ejemplo antes cuando explicamos por qué usar delimitadores diferentes.
En el ejemplo utilizamos la secuencia de caracteres \/
para escapar del delimitador de barra diagonal. Esto le dijo a nuestro procesador de expresiones regulares que la barra no era un delimitador. En cambio, le dijo al procesador de expresiones regulares que buscara literal de caracteres de barra oblicua.
Este ejemplo se aplica a todos los metacaracteres que vimos antes. Si quieres utilizar uno de ellos como literal de caracteres en tu expresión regular debes evitarlo con una barra invertida. Es por eso que a veces puedes ver una expresión regular con muchas barras invertidas. Simplemente significa que hubo que escapar muchos metacaracteres.
El escape también se utiliza para convertir literales de caracteres en clases de caracteres. Así, por ejemplo, puedes tener w
, que sea solo un literal de w. Pero también puedes escaparlo para que se convierta en \w
. \w
es una clase de caracteres de acceso directo que representa todos los caracteres alfanuméricos, así como _
. (Luego veremos algo más sobre la clase de carácter \w
)
Literales de caracteres coincidentes
¡Hablar sobre la clase de carácter \w
es un buen modo de presentar a nuestro próximo grupo de metacaracteres! Es el que se utiliza para unir literales de caracteres. Saber cuándo usar estos metacaracteres en lugar de literales de caracteres es una parte importante de saber cómo usar expresiones regulares.
Si no tienes claro qué es un literal de carácter, es simplemente una letra, un número o un símbolo como un signo de porcentaje. Imaginemos que tienes la siguiente expresión regular: /http:/
. Las cuatro letras y los dos puntos dentro de los delimitadores de expresiones regulares son literales de caracteres.
Clases de caracteres
Ahora, digamos que quieres representar un solo número entre 0 y 9. No existe un literal de carácter que represente todos esos números, ya que cada número es en sí mismo un literal de carácter. Ahí es donde entra en juego el concepto de clases de caracteres.
Las clases de caracteres, también denominadas en ocasiones como conjuntos de caracteres, son una forma de representar estos múltiples literales de caracteres que quieras hacer coincidir. Usamos corchetes ( []
) para contener estos caracteres literales. Esto le dice a la expresión regular que busque uno de estos literales de caracteres cuando busque una cadena.
Un pequeño ejemplo del uso literal de caracteres:
En inglés, puedes escribir la palabra optimize
con z
y con s
, dependiendo si usas el modo local de los EEUU o el Reino Unido. Si estás usando una expresión regular para buscar esa palabra con ambas ortografías, usarías esta expresión regular: optimi[zs]e
.
¿Qué rara es esta expresión regular, no? Bueno, la mayor parte son solo literales de caracters. Así que el procesador de expresiones regulares quiere hacer coincidir a o
, luego una p
, luego una t
y así sucesivamente con el resto de caracteres.
Bueno, eso es hasta que llegue al corchete de apertura. En ese punto, se detendrá y leerá lo que hay dentro de los corchetes, que son nuestros literales de caracteres z
y s
. Una vez hecho esto, intentará hacer coincidir uno de los dos literales de caracteres. Para finalizar, terminará intentando hacer coincidir el literal de carácter e
.
Representar una variedad de literales de caracteres.
Pero esto no resuelve del todo nuestro problema inicial. ¿Deberíamos simplemente representar números como [0123456789]
en nuestra expresión regular? Bueno, podrías, ¡pero no es necesario!
Las clases de caracteres también nos permiten representar rangos de literales de caracteres. En lugar de representar un número como [0123456789]
, puedes representarlo como [0-9]
. Esto hace que nuestra clase de caracteres ocupe menos espacio en nuestra expresión regular.
¡Incluso puedes representar letras del alfabeto usando un rango! Se vería así: [A-Za-z]
. Esta clase de caracteres cubre tanto las letras minúsculas como las mayúsculas del alfabeto. Pero si solo desea letras minúsculas, puedes usar [a-z]
. Lo mismo solo con letras mayúsculas, puedes usar [A-Z]
.
Atajos de clases de caracteres
Usar [A-Za-z0-9]
como clase de carácter siempre que quieras hacer coincidir una letra o un número es bastante lioso. Por suerte para nosotros, muchos procesadores de expresiones regulares tienen atajos para clases de caracteres comunes. Por ejemplo, puedes usar \w
(que mencionamos anteriormente) en tu expresión regular en lugar de la clase de caracteres [A-Za-z0-9_]
.
Cada procesador de expresiones regulares puede tener diferentes atajos. Dicho esto, hay algunos (como \w
) que son comunes a la mayoría de ellos. Los otros comunes son \d
y \s
. \d
es un atajo para la [0-9]
clase de caracteres que usas para hacer coincidir un número. Mientras tanto, \s
es un atajo para la clase de caracteres [ \t\r\n\v\f]
que se utiliza para hacer coincidir un carácter de espacio en blanco .
Metacaracteres dentro de clases de caracteres
Este es un buen momento para señalar que la mayoría de los metacaracteres no funcionan dentro de una clase de caracteres. Los únicos que funcionan son la barra invertida ( \
), el corchete de cierre ( ]
) y el acento circunflejo ( ^
). Vamos a hablar del acento circunflejo enseguida.
Si quieres utilizar uno de esos metacaracteres como literal de caracteres, debes escaparlos mediante una barra invertida. Es por eso que puedes usar una barra invertida en una clase de caracteres. Entonces, por ejemplo, [\^]
sería una clase de caracteres que coincidiría con un acento circunflejo como un literal de caracteres.
Pero también puedes usar la barra invertida para escapar de literales de caracteres. Vimos esto en la sección anterior cuando hablamos del atajo de clase de caracteres\s
. Así, por ejemplo, podemos representar una pestaña en una expresión regular usando \t
.
Clases de caracteres negados
¡Aquí hay otra cosa interesante que puedes hacer con las clases de caracteres! Puedes definir clases de caracteres que coincidan con cualquier cosa menos con lo que contienen. Se les llama clases de caracteres negados.
Por ejemplo, ahora sabemos que podemos usar la clase de caracteres [0-9]
para hacer coincidir un número. Entonces, ¿cómo reescribiríamos esa clase si quisiéramos decir que queremos hacer coincidir cualquier cosa menos un número? Bueno, ¡es sencillo! Sólo necesitas escribir la clase de tu personaje como [^0-9]
.
Con [^
es como definimos la clase de carácter negado. Cuando tu clase de caracteres comienza con a [^
, invierte el significado de la clase de caracteres. Le estás diciendo al procesador de expresiones regulares que deseas hacer coincidir cualquier literal de caracteres excepto los que están dentro de la clase de caracteres.
También existen atajos de clases de caracteres para nuestras clases de caracteres negados. En general, la clase de carácter abreviado para una clase de carácter negado es la versión en mayúscula de la normal. Entonces, si volvemos a las tres clases de caracteres de acceso directo que vimos antes, las clases de caracteres negados serían:
\W
que coincide con cualquier cosa menos un carácter literal alfanumérico.\D
que coincide con cualquier cosa menos un número.\S
que coincide con cualquier cosa menos un carácter de espacio en blanco.
Coincidir con (casi) cualquier literal de caracteres
Habrá ocasiones en las que no te importará el literal de caracteres que desea que coincida con tu expresión regular. Aquí es donde entra en juego el famoso metacarácter punto (.
).
Utiliza el punto cuando quieras hacer coincidir un literal de caracteres sin importar cuál sea ese literal de caracteres.
Los únicos literales de caracteres con los que un punto no coincidirá por defecto son los caracteres de salto de línea . Esto se debe a que, al principio, los procesadores de expresiones regulares trabajaban línea por línea y no en archivos completos. Esto significaba que no es necesario que el punto coincida con los saltos de línea.
Hoy en día, es bastante común querer aplicar una expresión regular a un archivo completo o a un gran bloque de texto. La mayoría de procesadores de expresiones regulares se adaptaron a esta necesidad. Tienen una opción para hacer que el punto coincida con todos los literales de caracteres, incluidos los de salto de línea.
El punto es un metacarácter muy potente. Lo vas a ver y utilizar mucho. Dicho esto, como ocurre con la mayoría de las cosas potentes, también es fácil hacer un mal uso.
El principal motivo para tener cuidado con el punto es que puede provocar errores imprevistos. Eso es debido a que el punto puede coincidir con cualquier cosa. Esto puede hacer que tu expresión regular coincida con algo que no esperabas.
Una mejor alternativa al punto es la clase de caracteres negados que hemos visto antes. Lo bueno de la clase de caracteres negada es que te obliga a no ser vago. Tienes que tomarte un momento y pensar en los literales de caracteres que no quieres que coincidan tu clase de caracteres. Luego vemos un ejemplo.
Cuantificadores
Hasta ahora, sólo hemos visto cómo representar un literal de caracteres o un grupo de literales de caracteres. No hemos visto cómo representar si queremos hacer coincidir varios de ellos en una fila. Aquí es donde debemos introducir el concepto de cuantificadores.
Los cuantificadores son una forma de decirle al procesador de expresiones regulares cuántas veces desea hacer coincidir un átomo (por si se te ha olvidado, un átomo puede ser un literal de caracteres, un metacarácter o una clase de caracteres). Hay tres metacaracteres cuantificadores principales.
Metacaracteres cuantificadores
El primer metacarácter cuantificador es el signo de interrogación ( ?
). Le dice al procesador de expresiones regulares que el átomo anterior es opcional. O, para decirlo de otra manera, el signo de interrogación es una forma de decir que desea hacer coincidir el átomo anterior 0 o 1 veces.
Por ejemplo, puedes utilizar el signo de interrogación para abordar la «o» frente a la «ou» en inglés estadounidense o britácnico. La expresión regular /behaviou?r/
coincidirá con behavior
y behaviour
.
El siguiente metacarácter cuantificador es el asterisco ( *
). Le dice al procesador de expresiones regulares que quieres hacer coincidir el átomo anterior 0 o más veces. Una combinación de átomo y cuantificador que encontrarás con frecuencia es el peligroso .*
.
.*
le dice a un procesador de expresiones regulares que desea hacer coincidir cualquier cosa durante el mayor tiempo posible.
El último metacarácter cuantificador es el signo más ( +
). Es muy similar al asterisco. Le dice al procesador de expresiones regulares que desea hacer coincidir el átomo anterior 1 o más veces.
Avaricia
Un concepto importante con los cuantificadores es la avaricia. Los cuantificadores le dan al procesador de expresiones regulares la opción de elegir entre dos opciones. Puede seguir haciendo coincidir el átomo que se repite o puede detenerse.
Por defecto, un procesador de expresiones regulares siempre es avaricioso. Siempre intentará hacer coincidir un átomo repetido tanto como pueda. Sólo dejará de hacer coincidir un átomo repetido cuando continuar haciéndolo impediría que el procesador de expresiones regulares encuentre una coincidencia.
Por eso, usar .*
es tan peligroso. Por defecto, el procesador de expresiones regulares coincidirá con cualquier carácter siempre que pueda. ¡Esto a menudo genera errores porque subestimamos cuánto tiempo el procesador de expresiones regulares seguiría haciendo coincidencias con .*
!
Un ejemplo de avaricia
Veamos un ejemplo clásico de este problema de avaricia. Ese problema es intentar hacer coincidir una etiqueta HTML. Imaginemos que tienes el siguiente HTML:
<p>Este es un párrafo con un enlace <a href="https://ejemplo.com"></a>.</p> _ _
La mayoría de las veces, comenzarás usando esta expresión regular: /<.*>/
. Es de esperar que esta expresión regular coincida con cada etiqueta HTML en ese bloque HTML. Pero no será así.
Debido a la avaricia, esta expresión regular coincidirá con todo el bloque HTML. Este es un error bastante común que cometen muchos desarrolladores.
Hacer vagos a los cuantificadores
Hay dos formas de resolver este problema. La primera es hacer que un cuantificador sea vago en lugar de avaricioso. Los cuantificadores vagos intentarán hacer coincidir el átomo repetido el menor número de veces posible.
Entonces, ¿cómo se convierte un cuantificador avaricioso en uno vago? ¡Es sencillo! Sólo tienes que añadir un signo de interrogación al final. ¡Esto también funciona para los tres metacaracteres cuantificadores que hemos visto hasta ahora!
??
es la versión vaga del metacarácter cuantificador ?
. Intentará hacer coincidir un átomo 0 veces en lugar de una vez, si puede. Mientras tanto, *?
y +?
son las versiones vagas de los metacaracteres cuantificadores *
y +
respectivamente. Ambos intentarán hacer coincidir un átomo lo menos posible en lugar de hacerlo lo más largo posible.
Esa es una forma de resolver el problema con .*
en nuestro ejemplo HTML. Puedes utilizar la versión vaga, que es .*?
.
Entonces, si cambias la expresión regular de /<.*>/
a /<.*?>/
, tu expresión regular coincidirá con cada etiqueta HTML en el bloque HTML.
Utiliza clases de caracteres negados
Dicho esto, la vagancia no es la única manera de hacer que un cuantificador sea menos avaricioso. Mencionamos anteriormente que la clase de carácter negado es una buena alternativa al metacarácter de punto. Bueno, ¡eso también es algo que podemos usar con cuantificadores!
Una clase de carácter negada también es una excelente manera de hacer que los cuantificadores sean menos avariciosos. Es un poco más complicado de visualizar cuando comienzas con expresiones regulares. ¡Pero para eso tenemos nuestro ejemplo HTML!
Así que volvamos a nuestro bloque HTML. Estamos intentando hacer coincidir todas las etiquetas HTML que contiene utilizando una expresión regular. El truco para utilizar una clase de carácter negado para hacer esto es pensar en lo que define una etiqueta HTML.
Ya sabemos lo que es eso. Es el signo menor que ( <
) y el signo mayor que ( >
). Por eso nuestra codiciosa expresión regular es /<.*>/
.
¡Pero esa es también la clave para reemplazar nuestro punto con una clase de carácter negada! Lo que realmente queremos que haga el punto es coincidir con cualquier cosa menos con el signo mayor que. ¡Esto, a su vez, nos dice el cambio que debemos realizar en nuestra expresión regular!
Necesitamos cambiar nuestra expresión regular de /<.*>/
a /<[^>]*>/
. Esto hará que coincida con todas las etiquetas HTML en nuestro bloque HTML. ¡No hay necesidad de un cuantificador vago!
Cuantificadores personalizados
Pero, ¿qué sucede cuando necesitas hacer coincidir un átomo un número específico de veces? ¿Cómo puedes definir que quieres, por ejemplo, que coincida un número 1 o 2 veces? En una situación como esa, querrás utilizar corchetes ( {}
) para definir cuántas veces quieres hacer coincidir un átomo.
El formato de los corchetes es {min,max}
. min
es el número mínimo de veces que quieres que el procesador de expresiones regulares coincida con tu átomo. max
es el número máximo de veces que quieres que coincida con tu átomo. Si no quieres establecer un número máximo de coincidencias, puedes dejarlo en blanco.
Quizás te hayas dado cuenta de que es posible representar el cuantificador que hemos visto hasta ahora usando corchetes. El cuantificador ?
es igual a {0,1}
, *
es igual a {0,}
y +
es igual a {1,}
. Estos metacaracteres de cuantificadores son en realidad solo atajos para estos cuantificadores personalizados comunes.
Agrupamiento
Hasta este punto, sólo hemos analizado los cuantificadores en el contexto de una repetición de un solo átomo. Pero, ¿qué sucede si es necesario comprobar si hay un patrón repetitivo de átomos? Bueno, para eso necesitas usar la agrupación.
Agrupar un grupo de átomos es bastante fácil. Sólo necesitas ponerlos entre paréntesis ( ()
). Esto le dice al procesador de expresiones regulares que quieres que utilice estos átomos como una sola unidad.
Por ejemplo, digamos que tienes esta expresión regular: /plato(s)?/
. Esta expresión regular coincidiría con la palabra «plato» o con su forma plural «platos». Esto se debe a que (s)?
le dice al procesador de expresiones regulares que coincida con los caracteres literales «s» 0 o 1 veces.
Elegir entre diferentes patrones de expresión regular
También puedes utilizar la agrupación para permitir que el procesador de expresiones regulares elija entre más de un patrón para que coincida. Esto no es diferente del operador «o» que usamos en programación. Esto puede resultar útil en muchas situaciones.
Un buen ejemplo de esto es si quieres buscar métodos de peticiones HTTP específicos . En tal escenario, es posible que quieras buscar únicamente los métodos GET y POST en un archivo de registro de acceso . Con expresiones regulares, representarías esta elección entre los dos métodos con (GET|POST)
.
El metacarácter de barra vertical ( |
) es el operador «o» para las expresiones regulares. Así es como representamos esta elección entre múltiples patrones. Se utiliza para separar las diferentes opciones de patrones que quieras que busque el procesador de expresiones regulares.
No hay límites en cuanto a la cantidad de opciones de patrones que puedes poner entre paréntesis. Dicho esto, debes tener en cuenta que el procesador de expresiones regulares siempre se detendrá cuando llegue a la primera coincidencia. Nunca intentará encontrar la mejor combinación entre todas las opciones.
Esto significa que debes tener cuidado al ordenar tus opciones de patrones. Por ejemplo, digamos que estás buscando una ruta URL como /ruta
y /ruta/valor
. Si lo escribe como /(\/ruta|\/ruta\/valor)/
( \/
es una barra diagonal con carácter de escape), el procesador de expresiones regulares nunca coincidirá con /ruta/valor
. En lugar de eso, querrás escribirlo como /(\/ruta\/valor|\/ruta)/
.
Capturando
Pero, ¿por qué debería importarte el orden de tus elecciones de patrones como acabamos de ver? Esto se debe a que las expresiones regulares no usan paréntesis únicamente para agrupar átomos. También los usan para algo llamado capturar.
La captura te permite almacenar parte de una cadena coincidente para su reutilización. Esto es útil si utilizas expresiones regulares para extraer información de una cadena. O si estás utilizando expresiones regulares para realizar una búsqueda compleja y reemplazarla dentro de un documento.
Grupo de captura numerado
Por defecto, un grupo de captura (así llamamos al bloque completo entre paréntesis) está numerado. ¿Qué significa esto? Bueno, digamos que tenemos una expresión regular como esta: /(\/ruta(\/[^\/]+))/
.
Esta es una variación de nuestra expresión regular anterior para una ruta de URL. Coincidirá con cualquier cadena que comience con /ruta
y que tenga un segundo subdirectorio después de /ruta
. Entonces, por ejemplo, /ruta
no coincidiría, pero /ruta/valor
sí.
Esta expresión regular también tiene dos grupos de captura. El primero abarca toda la expresión regular. El segundo es sólo para el subdirectorio posterior a /ruta
.
Este orden también representa el número de cada grupo de captura. /(\/ruta(\/[^\/]+))/
es el grupo de captura n.° 1. Puedes hacer referencia a él como \1
en una expresión regular o $1
cuando uses PHP o una aplicación como un editor de texto.
Grupo de captura con nombre
Los grupos de captura numerados como los que acabamos de ver a menudo pueden ser complicados de usar con expresiones regulares grandes. Si añades o eliminas grupos de captura, los números que representan esos grupos de captura pueden cambiar. Esto dificulta realizar cambios en la expresión regular sin causar errores.
Para resolver este problema, la mayoría de los procesadores de expresiones regulares modernos le permiten nombrar grupos de captura. Este nombre reemplaza el número que usó antes para hacer referencia a un grupo de captura. Esto te permite hacer referencia a un grupo de captura sin tener que preocuparse de que la referencia pueda cambiar.
Entonces, ¿cómo se utilizan grupos de captura con nombre? Bueno, ¡actualicemos nuestra expresión regular anterior para usarlas y que puedas ver! Nombraremos el primer grupo de captura ruta_completa y al segundo grupo de captura subdir
.
/(?<ruta_completa>\/ruga(?<subdir>\/[^\/]+))/
es nuestra expresión regular actualizada con grupos de captura con nombre. Notarás que la forma de definir un grupo de captura con nombre es usando (?<name>
al principio. Sólo tienes que reemplazar name
con el nombre que quieras usar para tu grupo de captura.
Anclajes
Hasta ahora, los metacaracteres que hemos visto siempre se usaban de una manera específica. Siempre los usamos para intentar hacer coincidir un literal de un solo carácter o un grupo de literales de caracteres. Este no será el caso con este último conjunto de metacaracteres.
A estos metacaracteres los llamamos «anclajes». A diferencia de los otros metacaracteres que hemos visto, no representan caracteres literales. En cambio, los usamos para hacer coincidir una posición específica dentro de una cadena.
Los dos anclajes que verá utilizados con mayor frecuencia son el acento circunflejo ( ^
) y el signo de dólar ( $
). El acento circunflejo representa la posición inicial de una cadena. Mientras tanto, el signo de dólar representa la posición final de una cadena.
Entonces, imaginemos que tenemos esta expresión regular: /^\/ruta$/
. Esta expresión regular sólo coincidiría con la cadena /ruta
. Esto se debe a que utilizamos los anclajes de posición inicial y final.
Sin embargo, si quieres hacer coincidir una cadena que comience con /ruta
, simplemente debes usar la expresión regular /^\/ruta/
. Esta es la misma expresión regular sin el anclaje de posición final.
Este es un uso mucho más común de anclajes. Suelen usarse para asegurarse de que una cadena comience o termine de una manera específica. No es tan común (ni útil) utilizar ambos anclajes en la misma expresión regular.
Modificadores
Entonces digamos que tienes una lista de rutas URL como esta:
/ruta/algo /otra-ruta/otro-algo /ruta/otro-algo-distinto
¿Qué pasaría si usaras la expresión /^\/ruta/
que acabamos de ver? Bueno, es de esperar que el procesador de expresiones regulares coincida con la primera y la última ruta URL de esa lista. Como puedes imaginar, eso no es lo que sucederá.
Solo coincidirá con la primera ruta URL y no con la segunda. Esto se debe a que, por defecto, un procesador de expresiones regulares considera un bloque de texto como una sola cadena. Eso significa que el anclaje de intercalación solo coincide con la posición inicial al comienzo del bloque de texto.
Aquí es donde entran los modificadores. Los modificadores son indicadores que te permiten cambiar cómo un procesador de expresiones regulares procesará tu expresión regular. En general, tiendes a añadirlos después del delimitador de tu expresión regular.
Modificadores útiles
Hay muchos modificadores diferentes. Dicho esto, en esta guía solo nos centraremos en algunos útiles, y que suelen ser los más utilizados.
El primer modificador útil que usarás con bastante frecuencia es i
. Hace que tu expresión regular no distinga entre mayúsculas y minúsculas. Por ejemplo, digamos que tienes /esto/i
como expresión regular. Coincidiría con cualquier variación de «esto» con letras minúsculas y mayúsculas.
El siguiente modificador que debes conocer es s
. Hace que el punto coincida con todos los caracteres posibles, incluidos los saltos de línea. Esto es útil cuando usas una expresión regular en grandes bloques de texto (esto se usa muuucho).
<strong>
Algún texto en negrita
</strong>… …
No es inusual tener un bloque tipo HTML como el de arriba. Si tratases de usar la expresión regular /<strong>.*<\/strong>/
no funcionaría debido a los saltos de línea. Pero la expresión regular /<strong>.*<\/strong>/s
sí podría gracias al modificador s
.
Nota:
/<strong>[^<]*<\/strong>/
no necesitaría el modificador. ¡Esa es otra razón por la que las clases de caracteres negadas son súper útiles!
El último modificador que es útil conocer es m
. Este modificador hace que el acento circunflejo y el signo de dólar coincidan con la posición inicial y final de una línea en lugar de una cadena. Este es el modificador que necesitarías usar para solucionar el problema con la expresión regular anterior \^\/ruta\
.
Bueno, y llegamos al final del repaso (general) a la sintaxis de las expresiones regulares. Hay muuucho, muuuuuuucho más, pero esto es lo fundamental y lo que más utilizarás.
Ahora vamos a ver cómo aplicar estos conocimientos para mi sitio WordPress.
Por qué hacer redirecciones con expresiones regulares usando un plugin
Por supuesto, podrías crear redirecciones mediante expresiones regulares añadiéndolas mediante PHP, JavaScript o incluso directamente en el archivo .htaccess de tu servidor, pero hay algunas ventajas que considero importantes a hacerlo con un plugin, en concreto con Redirection:
- Puedes gestionar todas las redirecciones directamente desde el escritorio de tu WordPress, lo que permite a usuarios no técnicos ver y actualizar las redirecciones cuando sea necesario.
- Puedes realizar un seguimiento del número de visitas a tus redirecciones, y también realizar un seguimiento de los errores 404.
- Puedes usar esto incluso si tu servidor no ejecuta Apache o no te permite editar .htaccess (que es el método alternativo para añadir redirecciones en la mayoría de los casos).
Redirecciones con expresiones regulares con el plugin Redirection
Para añadir una redirección mediante expresiones regulares con el plugin Redirection (gratuito), después de instalarlo y activarlo como cualquier otro plugin, como es lógico, ve a su página de ajustes, en «Herramientas → Redirection» y haz clic en el botón «Añadir nueva», con lo que se desplegará el formulario de creación de redirecciones.
Lo primero que debes hacer una vez aquí es elegir en el desplegable de la derecha de «Opciones de URL / Regex» la opción de «Expresión regular», y si también lo vas a usar, marcar también las opciones de «Ignorar barra inclinada» y/o «Ignorar mayúsculas/minúsculas», si te sirve para la redirección que vayas a hacer.
Hecho esto ya solo te queda completar los campos de URL de origen y de destino, aplicando las expresiones regulares que hagan el tipo de redirección que necesites, y aplicando la sintaxis que hemos aprendido antes.
Estos serían algunos de los ejemplos más habituales en instalaciones de WordPress:
- Redirección de fecha y hora a nombre de entrada:
Origen:^/\d{4}/\d{2}/\d{2}/(.*)
Destino:/$1/
Ejemplo:/2020/01/01/hola-mundo/
=>/hola-mundo/
- Redirección de fecha, hora, nombre y categoría a nombre de entrada:
Origen:^/\d{4}/\d{2}/\d{2}/.*?/(.*)
Destino:/$1/
Ejemplo:/2020/01/01/category/general/hola-mundo/
=>/hola-mundo/
- Redirección de todos los contenidos de un sitio antiguo a uno nuevo:
Origen:/(.*)
Destino:https://dominionuevo.com/$1/
Ejemplo:http://dominioantiguo.com/hola-mundo/
=>https://dominionuevo.com/hola-mundo/
- Redirección para quitar index.php de la URL:
Origen:/index\.php/(.*)
Destino:/$1/
Ejemplo:http://midominio.com/index.php/hola-mundo.html
=>https://midominio.com/hola-mundo/
¿Me animo ya a hacer mis primeras redirecciones con expresiones regulares?
Por muy bien que hayas entendido esta guía, no te lances a crear redirecciones con expresiones regulares en webs de clientes o sitios con tráfico real.
Primero haz siempre pruebas en una web a la que tengas acceso total, para poder modificar archivos, recuperar una copia de seguridad limpia, etc., por si sale mal alguna redirección.
Una vez hayas ganado confianza con la redirección REGEX concreta que quieras hacer en la web real, y hayas comprobado que funciona a la perfección, sin errores ni bucles infinitos, ya puedes lanzarte a realizar la en el sitio real.
Para aprender más sobre expresiones regulares
Si quieres ampliar conocimientos estos enlaces pueden ayudarte:
¿Te gustó este artículo? ¡Ni te imaginas lo que te estás perdiendo en YouTube!