6.- Expresiones regulares

La expresiones regulares (ER) son una forma de describir cadenas de caracteres. Se usan en operaciones de emparejamiento o comparación. Las expresiones regulares permiten realizar búsquedas o sustituciones de gran complejidad.

Las búsquedas en el editor vi con los comandos / y ? aceptan expresiones regulares; esto hace las búsquedas mucho más potentes y flexibles. Las expresiones regulares son aceptadas en otros editores y en muchos comandos, si bien con algunas diferencias de sintaxis.

Una expresión regular es un patrón que describe un conjunto de cadenas de caracteres. Por ejemplo, el patrón aba*.txt describe el conjunto de cadenas de caracteres que comienzan con aba, contienen cualquier otro grupo de caracteres, luego un punto, y finalmente la cadena txt. El símbolo * se interpreta como «0, 1 o más caracteres cualesquiera«.

Las expresiones regulares se construyen como las expresiones aritméticas, usando operadores para combinar expresiones más pequeñas. Analizaremos esos operadores y las reglas de construcción de expresiones regulares, atendiendo siempre al conjunto de cadenas que representa cada patrón.

Meta-caracteres

La construcción de expresiones regulares depende de la asignación del significado especial para algunos caracteres. En el patrón aba*.txt el carácter * no vale por sí mismo, como el carácter asterisco, sino que indica un «conjunto de caracteres cualesquiera». Asimismo, el carácter ? no se interpreta como el signo de interrogación sino que representa «un carácter cualquiera y uno solo». Estos caracteres a los que se asigna significado especial se denominan «meta-caracteres». El conjunto de meta-caracteres para expresiones regulares es el siguiente:

Estos caracteres, en una expresión regular, son interpretados en su significado especial y no como los caracteres que normalmente representan. Una búsqueda que implique alguno de estos caracteres obligará a «protegerlo» de la interpretación mediante \, tal y como se hace para evitar la interpretación de los meta-caracteres en el shell. En una expresión regular, el carácter ? representa «un carácter cualquiera«; si escribimos \?, estamos representando el carácter ? tal cual, sin su significado adicional.

Expresiones Regulares Básicas

Una expresión regular determina un conjunto de cadenas de caracteres. Un miembro de este conjunto de cadenas se dice que junta, equipara o satisface la expresión regular.

ERs de un sólo carácter

Las expresiones regulares se componen de expresiones regulares elementales que aúnan en un único carácter:

Los paréntesis rectos [ ] delimitan listas de caracteres individuales. Muchos meta-caracteres pierden su significado si están dentro de las listas: los caracteres especiales . * [ \ mantiene el valor dentro de [ ]. Para incluir un carácter ] en una lista, colocarlo al principio; para incluir un ^ colocarlo en cualquier lugar menos al principio; para incluir un colocarlo al final.

Dentro de los conjuntos de caracteres individuales, se reconocen las siguientes categorías:

[:alnum:]    alfanuméricos
[:alpha:]    alfabéticos
[:cntrl:]    de control
[:digit:]    dígitos
[:graph:]    gráficos
[:lower:]    minúsculas
[:print:]    imprimibles
[:punct:]    de puntuación
[:space:]    espacios
[:upper:]    mayúsculas
[:xdigit:]   dígitos hexadecimales 

Por ejemplo, [[:alnum:]] significa [0-9A-Za-z], pero esta última expresión depende de la secuencia de codificación ASCII, en cambio la primera es portable, no pierde su significado bajo distintas codificaciones. En los nombres de categorías, los paréntesis rectos forman parte del nombre de la categoría y no pueden ser omitidos.

Construcción de Expresiones Regulares

Una Expresión Regular se construye con uno o más operadores que indican, cada uno, el carácter a buscar. Los operadores más comunes y aceptados son los siguientes:

Ejemplos de Expresiones Regulares Básicas

En el editor vi, las expresiones regulares permiten realizar búsquedas tales como:

/^Desde.- Busca líneas que empiecen con la cadena Desde
/final$.- Busca líneas que termine con la cadena final
/\$25  .- Busca líneas que contengan $25
\      .- Protege a $

Expresiones Regulares Extendidas

Algunos comandos, como egrep o grep -E, aceptan Expresiones Regulares Extendidas, que comprenden las Expresiones Regulares Básicas más algunos operadores que permiten construcciones más complejas. Los operadores incorporados son los siguientes:

La repetición tiene preferencia sobre la concatenación; la concatenación tiene preferencia sobre la alternativa. Una expresión puede encerrarse entre paréntesis para que sea  evaluada primero.

Expresiones regulares en GNU

En GNU, no se distinguen expresiones regulares básicas de extendidas; los comandos aceptan todas las expresiones regulares. En ese caso, como siempre se están usando extendidas, los meta-caracteres ?, +, {, |, (, y ) deben ser protegidos cuando se quieran usar como caracteres normales, escribiendo \?, \+, \{, \|, \(, y \).

Ejercicios de prácticas

En algunos de los ejercicios que siguen se pide usar el archivo ejemplo.docDescargalo y cópialo en tu  directorio de trabajo antes de comenzar. Los comandos grep y grep -E buscan líneas que contengan expresiones regulares básicas y extendidas, respectivamente.

1. El archivo ejemplo.doc fue obtenido de Internet. Usar el editor vi (o tu editor favorito)en sólo lectura, para verificar la presencia del carácter visualizado como «^M«, correspondiente a retorno de carro (CR). Crear el archivo historia1.txt, eliminando el carácter CR. Verificar con vi.

2. Abrir el archivo historia1.txt con el editor vi, en sólo lectura. Buscar hacia adelante (comando /), la palabra «Uruguay». Reiterar la búsqueda (comando n) hasta verificar que recomienza al principio del archivo. Repetir hacia atrás (comando ?).

3. Con el comando grep, extraer del archivo historia1.txt las líneas que empiecen con la cadena «es«. Buscar luego líneas que terminen con la cadena «del«.

4. Crear el archivo palabras.txt, que contiene todas las palabras del archivo historia1.txt, una por línea. Recordar que en español existen la ñ y las vocales acentuadas. Verificar con vi -R o more.

5. Una misma palabra puede a veces contener una mayúscula, o estar escrita totalmente en mayúsculas, lo que la hará  aparecer como palabras distintas. Crear el archivo palabras.min con todas las palabras del archivo palabras.txt en minúsculas.

6. En el archivo historia1.txt mostrar
a) líneas que empiecen con «a«;
b) líneas que terminen con «l«;
c) líneas que empiecen con «e» y terminen con «l«.

7. En el archivo historia1.txt mostrar
a) líneas que contengan la palabra «ganado«;
b) líneas que contengan la palabra «gaucho» y «ganado«;
c) líneas que contengan la palabra «ganado» pero no la palabra «vacuno«.

8. En un archivo de texto se debe determinar
a) cantidad de líneas que contengan la cadena «se«.
b) cantidad de líneas que contengan la palabra «se«.
c) cantidad de líneas que contengan «se» dentro de una palabra.
d) líneas que contengan al mismo tiempo la palabra «se» separada y la cadena «se» como parte de palabra.
Construir primero un «juego de prueba» (un archivo de texto) contemplando todas las posibilidades de ubicación de los caracteres «se» como palabra y como cadena, en el medio y a los extremos de palabra, al principio de línea o al final de línea, etc. Verificar la correcta detección en todos los casos pedidos. Verificar finalmente que la suma «cierra«.

9. Crear el archivo histo1.txt con las primeras 5 líneas del archivo historia1.txt que contengan sólo minúsculas y eliminando las líneas en blanco. Eliminar la primera línea en blanco parece difícil. ¿Puede hacerse?

10. Sin considerar vocales acentuadas, mostrar el archivo histo1.txt
a) con las vocales en mayúsculas y las consonantes en minúsculas;
b) con las vocales en minúscula y las consonantes en mayúscula.

11. Mostrar el archivo historia1.txt eliminando todas las vocales, sean éstas mayúsculas o minúsculas y estén acentuadas o no. ¿Puede leerse el texto tal como queda?

12. Un diptongo está  formado por dos vocales, una fuerte y una débil, o dos débiles. Las vocales fuertes son a, e, o; las vocales débiles son i, u. La acentuación de u o i destruye el diptongo. En el archivo historia1.txt
a) mostrar todas las palabras con diptongo formado por dos vocales débiles, ordenadas y sin repetir;
b) mostrar del mismo modo todos los diptongos con a;
c) buscar una expresión regular mínima que despliegue todos los diptongos.

13. Usando el archivo /etc/passwd, y el listado de usuarios con  ypcat passwd si el sistema usa NIS, extraer los siguientes registros:
a) usuarios con la palabra «Unix» al principio del campo de comentario.
b) usuarios del grupo 101.
c) usuarios de los grupos 100, 101 o 105.
d) usuarios con directorio propio de la forma «/home/un*«.
e) usando /etc/passwd, listar usuarios con UID de 1 dígito.
f) usando /etc/passwd, listar usuarios con UID de 1 o 2 dígitos
g) usuarios con nombre de exactamente 4 caracteres.
h) usuarios con nombre de 4 caracteres empezando con r.

  • Con esta batería de ejercicios espero que os sirvan para coger soltura con las expresiones regulares.