Aparte de para las labores habituales de todo desarrollador (o sea, escribir código, jeje), Visual Studio es también una estupenda herramienta para procesar archivos, sobre todo cuando necesitas hacer cambios masivos en contenidos mediante buscar y reemplazar. Como te permite abrir muchos archivos y luego buscar cadenas sobre ellos usando expresiones regulares, puedes hacer cambios más o menos complejos con relativa facilidad.

Sin embargo la sintaxis de expresiones regulares que admite difiere en bastantes cosas de la sintaxis habitual en la mayoría de los lenguajes de programación, como C#/.NET o JavaScript, por ejemplo.

Para expresiones regulares básicas es igual y no tendrás problemas, pero hay otras cuestiones que, de entrada, resultarán más complejas porque cambia la sintaxis.

Por ejemplo, imagina que tienes que cambiar todas las etiquetas <ul>  dentro de varios archivos HTML por etiquetas <ol>, para convertir todas las listas en listas ordenadas.

Abrirías el diálogo de buscar y reemplazar (CTRL+H) y podrías probar con esta configuración:

BuscarExpReg_1

La expresión regular (\<ul.*\>) no tiene nada raro aparentemente: busca las cadenas que empiecen por <ul y contengan (o no) lo que sea dentro de la etiqueta, cerrándose, claro está, con un “>”.

Si tenemos algo como esto:

BuscarExpReg_2

Encontrará sin problema el <ul> que tenemos.

Sin embargo consideremos este otro código:

BuscarExpReg_3

Algún diseñador HTML desbocado nos ha puesto en la misma línea toda la línea. Si ahora hacemos uso del diálogo anterior para hacer la búsqueda, el primer <ul> aparecerá sin problemas como antes, pero esto es lo que encontrará la expresión para el segundo:

BuscarExpReg_4

Efectivamente: la línea entera.

El problema es que por defecto, como en casi todos los lenguajes, las expresiones regulares son “codiciosas” (o en inglés “greedy”). Por ello tratan de que se cumpla la expresión pero de la manera más amplia posible. Es decir, si le ponemos “.*\>” tratará de buscar cualquier cadena de cualquier longitud (el punto con el asterisco) que termine con un “>”. Como es “codiciosa” por defecto, buscará la más larga posible. En una línea como la resaltada en la figura anterior (por defecto no son multi-línea) la expresión se extiende hasta alcanzar el último “>” de la misma. Pero eso no es lo que nosotros queremos.

Para evitar este problema en una expresión regular común en C# o JavaScript usamos el operador “?”. Este operador a continuación de un modificador de longitud estilo “*” o “+” indica que éste debe comportarse de la manera menos codiciosa posible (non-greedy). Si intentamos meter este operador en el diálogo de Visual Studio veremos que, directamente, no encuentra nada.

El motivo es que las expresiones regulares de VS consideran este operador “?” como  una interrogación más, es decir, sería como decirle que la cadena debe terminar con una interrogación y un mayor.

Entonces ¿cómo se consiguen expresiones non-greedy en Visual Studio?

Pues muy sencillo. Simplemente hay que utilizar la sintaxis especial que le han otorgado (la verdad es que deberían haber usado una sintaxis común, la misma que en –NET para evitar problemas, pero sus buenas razones tendrían quiero pensar).

De hecho precisamente por esta sintaxis especial es necesario marcar los símbolos “>” y “<” como “\>” y “\<”, es decir, con caracteres de escape, porque de otro modo éstos indican el fin y el principio de línea respectivamente (en condiciones normales no habría que “escapearlos”).

Si vemos con detenimiento la tabla de caracteres de control especiales para estas expresiones regulares nos daremos cuenta de que Visual Studio utiliza dos caracteres especiales propios para indicar coincidencias no-codiciosas:

· @: es equivalente a “*?” en expresiones regulares convencionales. Es decir, coincide con cualquier número de caracteres de manera no codiciosa, incluyendo el hecho de que no haya ninguno (o sea, puede haberlos o no).

· #: es equivalente a “+?” en expresiones regulares convencionales. Es decir, coincide con cualquier número de caracteres excepto 0 de manera no codiciosa. Es decir, que debe haber al menos una coincidencia.

Así, en el caso anterior, podríamos usar este diálogo para encontrar correctamente los <ul> de nuestras páginas:

BuscarExpReg_5

Es decir, la expresión regular se descompone en los siguientes elementos:

· “\<ul”: la cadena debe empezar por “<ul”

· “.@”: cualquier caracter, el número de veces que sea, incluyendo el hecho de que no exista ninguno. Así encaja con <ul> y también con <ul class=”Lista”> o con cualquier otro atributo que tenga la etiqueta. El caracter @ indica que debe ser non-greedy, es decir, que debe detectar la cadena más corta posible.

· “\>”: la cadena debe terminar con un “>”, como todas las etiquetas HTML.

Fácil, pero cuando intentas usar expresiones regulares normales puedes volverte loco´. Así que ya sabes, ten a mano siempre el enlace anterior y verifica los caracteres especiales que usa Visual Studio para sus búsquedas.

El objetivo de este post era llamar la atención sobre esta sintaxis especial, ayudar a alguno que tuviera problemas con el uso de esta herramienta y, de paso, repasar los mínimos de las expresiones regulares, algo que todo programador debería conocer al dedillo trabaje en el lenguaje que trabaje :-)

¡Espero que te sea útil!

💪🏻 ¿Este post te ha ayudado?, ¿has aprendido algo nuevo?
Pues NO te pido que me invites a un café... Te pido algo más fácil y mucho mejor

Escrito por un humano, no por una IA