loading
FullScreen Fecha y Hora: 29-Apr-2024 02:08 IP Pública: 3.144.93.73 Usuario: Público
18/Jun/2010 EXPRESIONES REGULARES

EXPRESIONES REGULARES

 

Introducción
Vamos a explicar las expresiones regulares porque se utilizan a menudo desde una gran variedad de aplicaciones en los SO tipo Unix como Linux. Permiten reconocer una serie de cadenas de caracteres que obedecen a cierto patrón que llamamos expresión regular. Por ejemplo si deseamos buscar lineas que contenga las palabras 'hola' o 'adiós' en los ficheros del directorio actual haremos:

$ egrep 'hola|adiós' *

No todos los comandos usan de forma idéntica las expresiones regulares. Algunos de los comandos que usan expresiones regulares son 'grep', 'egrep', 'sed', 'vi', y 'lex'. Este último en linux se llama 'flex' y es un analizador sintáctico muy potente pero no lo explicaremos porque para usarlo hay que saber lenguaje 'C'. Actualmente algunos lenguajes modernos como el 'perl' incluyen capacidad de manejar expresiones regulares lo cual les da una gran potencia y para lenguajes más antiguos como el 'C' existen librerías para poder usar expresiones regulares. En resumen las expresiones regulares están sinedo incorporadas en distintos sitios y ya no están limitadas a su uso en SO tipo Unix. Cada comando o aplicación implementa la expresiones regulares a su manera aunque en general son todas bastantes parecidas. Por ejemplo 'grep' permite usar expresiones regulares sencillas mientras que 'egrep' es capaz de usar expresiones regulares más complejas. Otros comandos adaptan el uso de expresiones a sus particulares necesidades y por ello si bien se puede hablar en general de ellas hay que tener en cuenta las peculiaridades de cada caso que deberán ser consultadas en las paginas del manual de cada comando. Las expresiones regulares vienen a ser una especie de lenguaje y cada comando usa su propio dialecto. En realidad las diferencias entre los distintos dialectos suelen ser muy pocas. Por ejemplo si un comando usa los paréntesis y además admite el uso de expresiones regulares extendidas se establecerá una forma de distinguir si los paréntesis deben ser interpretados como patrón de la expresión regular o como otra cosa. Para ello se suele usar los paréntesis precedidos del carácter escape '\'. Vamos a tomar a 'egrep' y 'sed' como comandos para aprender expresiones regulares porque este curso tiene un enfoque práctico. Usaremos el comando 'egrep' con distintos patrones y veremos cuando cumple y cuando no cumple y de esa forma se entenderá perfectamente.

Operadores usados en expresiones regulares.

 

* El elemento precedente debe aparecer 0 o más veces.
+ El elemento precedente debe aparecer 1 o más veces.
. Un carácter cualquiera excepto salto de linea.
? Operador unario. El elemento precedente es opcional
| O uno u otro.
^ Comienzo de linea
$ Fin de linea
[...] Conjunto de caracteres admitidos.
[^...] Conjunto de caracteres no admitidos.
- Operador de rango
(...) Agrupación.
\ Escape
\n Representación del carácter fin de linea.
\t Representación del carácter de tabulación.

Esta lista no es completa pero con esto es suficiente para hacer casi todo lo que normalmente se hace con expresiones regulares.

Ejemplos para cada operador con 'egrep'
Empezaremos usando un ejemplo lo más sencillo posible para ilustrar cada uno de estos operadores

Ejemplo para el operador '*' con el patrón 'ab*c'
Este patrón localizará las cadenas de caracteres que
empiecen por 'a', que continúen con 0 o más 'b', y
que sigan con una 'c'.

La 4 falla porque la 'a' y la 'c' no van seguidas ni
existen caracteres 'b' entre ambas. La 5 falla por no
tener una sola 'c'. y la 6 tiene los caracteres adecuados
pero no en el orden correcto.

$ egrep 'ab*c' <
< 1 ac
< 2 aac
< 3 abbbc
< 4 axc
< 5 aaab
< 6 cba
< 7 aacaa
< FIN

1 ac
2 aac
3 abbbc
7 aacaa

 

Ejemplo para el operador '+' con el patrón 'ab+c'
Este patrón localizará las cadenas de caracteres que
empiecen por 'a', que continúen con 1 o más 'b', y
que sigan con una 'c'.

Solo la línea 3 cumple la expresión regular.

$ egrep 'ab*c' <
< 1 ac
< 2 aac
< 3 abbbc
< 4 axc
< 5 aaab
< 6 cba
< 7 aacaa
< FIN

3 abbbc

 

Ejemplo para el operador '.' con el patrón 'a..c'
Este patrón localizará las cadenas de caracteres que
empiecen por 'a', que continúen con dos caracteres
cualesquiera distintos de salto de línea y que sigan
con una 'c'.
$ egrep 'a..c' <
< a00c
< axxcxx
< aacc
< abc
< ac
< axxxc
< FIN

a00c
axxcxx
aacc

 

Ejemplo para el operador '?' con el patrón 'ab?cd'
Este patrón localizará las cadenas de caracteres que
empiecen por 'a', y que opcionalmente continúen con
una 'b' y que continúe con los caracteres 'cd'.
$ egrep 'ab?cd' <
< abcd
< acd
< cd
< abbcd
< FIN

abcd
acd

 

Ejemplo para el operador '|' con el patrón 'ab|cd'
Este patrón localizará las cadenas de caracteres que
contengan 'ab', 'cd', o '123'
$ egrep 'ab|cd|123' <
< xxxabzzz
< xxxcdkkk
< badc
< dbca
< x123z
< FIN

xxxabzzz
xxxcdkkk
x123z

 

Ejemplo para el operador '^' con el patrón '^abc'
Este patrón localizará las lineas que empiecen
por 'abc'.
$ egrep '^abc' <
< abcdefgh
< abc xx
< 00abc
< FIN

abcdefgh
abc xx

 

Ejemplo para el operador '$' con el patrón 'abc$'
Este patrón localizará las lineas que terminen
por 'abc'.
$ egrep 'abc$' <
< abcd
< 000abc
< xxabcx
< abc
< FIN

000abc
abc

 

Ejemplo para el operador '[ ]' con el patrón '0[abc]0'
Este patrón localizará las cadenas que tengan un '0'
seguido de un carácter que puede ser 'a', 'b', o 'c' y
seguido de otro '0'.
$ egrep '0[abc]0' <
< 0abc0
< 0a0
< 0b0
< 0c0
< xax
< FIN

0a0
0b0
0c0

 

Ejemplo para el operador '^' (negación) dentro de '[ ]'
con el patrón '0[^abc]0'
Este patrón localizará las cadenas que tengan un '0'
seguido de un carácter que no podrá ser ni 'a', ni 'b',
ni 'c' y seguido de otro '0'.
$ egrep '0[^abc]0' <
< 0abc0
< 0a0
< 000
< x0x0x
< 0c0
< FIN

000
x0x0x

 

Ejemplo para el operador '-' (rango) dentro de '[ ]'
con el patrón '0[a-z]0'
Este patrón localizará las cadenas que tengan un '0'
seguido de una letra minúscula, y seguido de otro '0'.
$ egrep '0[a-z]0' <
< 0a0
< 000
< 0Z0
< x0x0x
< FIN

0a0
x0x0x

 

Ejemplo para el operador '()' (agrupación) con el
patrón '0(abc)?0'
Este patrón localizará las cadenas que tengan un '0'
seguido opcionalmente de la secuencia abc, y seguido
de otro '0'.
$ egrep  '0(abc)?0' <
< hh00hh
< s0abc0s
< s0ab0s
< 0abc
< FIN

hh00hh
s0abc0s

 

Ejemplo para el operador '\' (escape) con el
patrón '0\(abc\)?0'
Este patrón localizará las cadenas que tengan un '0'
seguido opcionalmente de la secuencia abc, y seguido
de otro '0'.
$ egrep  '0\(abc\)?0' <
< 0(abc)0xx
< 0(abc0xx
< hh00hh
< FIN

0(abc)0xx
0(abc0xx

 

Ampliando conocimientos sobre 'egrep'
Hemos aprendido cosas de egrep para ilustrar el uso de las expresiones regulares pero tanto grep como egrep permiten el uso de ciertas opciones que aún no hemos comentado y que no vamos a ilustrar con ejemplos porque no están relacionadas con las expresiones regulares. Solo vamos a señalar las opciones más útiles para que las conozca.

 

Para un mayor detalle consultar las páginas del manual. Se trata de un comando de gran utilidad y le recomendamos que practique por su cuenta con el. Exísten varias modalidades de este comando.

 

Uso de expresiones regulares en 'sed'
Ahora veremos unos ejemplos con 'sed'. Este comando es capaz de editar un flujo o chorro de caracteres lo cual es de enorme utilidad dado que muchos comandos se comunican a través de entrada salida mediante chorros de caracteres. No podemos ver todas las posibilidades de 'sed' porque lo que nos interesa es su uso con expresiones regulares. Para ello usaremos un nuevo operador '&' que en la parte de substitución de 'sed' indica la parte que coincide con la expresión regular.

Para usar 'sed' se pone como primer argumento a continuación del comando la orden adecuada. Opcionalmente se puede poner un segundo parámetro que indicaría el nombre de un fichero. De no existir ese segundo parámetro esperará la entrada por la entrada estándar.

Se intentan reconocer las secuencias más largas posibles ^ y $ no consumen carácter '\n' si.

Empezamos con una sustitución sencillita.

$ echo "abc1234def" | sed "s/[0-9][0-9]*/NUMERO/"

abcNUMEROdef

Ahora usamos el operador '&'. Observe como se sustituye por el patrón reconocido.

$ echo "abc1234def" | sed "s/[0-9][0-9]*/<&>/"

abc<1234>def

Después eliminamos la secuencia numérica.

$ echo "abc1234def" | sed "s/[0-9][0-9]*//"

abcdef

Vamos a comprobar que en las expresiones regulares se intenta siempre reconocer la secuencia más larga posible.

$ echo "000x111x222x333" | sed "s/x.*x/<&>/"

000333

Vamos ahora a trabajar sobre un fichero. Como siempre recordamos que trabaje con un usuario sin privilegios y dentro de /tmp. Ya sabe como hacerlo así que cambie ahora a /tmp antes de continuar. Para suprimir del fichero la palabra 'Hola' en las lineas de la 3 a la 4.

# Creamos un ficherito de prueba
$ cat < prueba-sed.txt
< Hola este es un fichero con datos de prueba
< Hola otra vez.
< Hola otra vez.
< Hola otra vez.
< Hola otra vez y otra y otra y otra y otra y otra.
< Fin de los datos de prueba
< FIN
$ sed "3,4s/Hola//" prueba-sed.txt

Hola este es un fichero con datos de prueba
Hola otra vez.
otra vez.
otra vez.
Hola otra vez y otra y otra y otra y otra y otra.
Fin de los datos de prueba

El fichero no ha cambiado. El resultado sale por salida estándar. Ahora veamos que pasa si intentamos sustituir la palabra 'otra' por la palabra 'una' en todo el fichero.

$ sed "s/otra/una/" prueba-sed.txt

Hola este es un fichero con datos de prueba
Hola una vez.
Hola una vez.
Hola una vez.
Hola una vez y otra y otra y otra y otra y otra.
Fin de los datos de prueba

Vemos que solo se ha cambiado la primera ocurrencia de cada línea. Para obtener el resultado deseado tendríamos que usar la g al final.

$ sed "s/otra/una/g" prueba-sed.txt

Hola este es un fichero con datos de prueba
Hola una vez.
Hola una vez.
Hola una vez.
Hola una vez y una y una y una y una y una.
Fin de los datos de prueba

Ampliando conocimientos sobre 'sed'
Hemos aprendido cosas de sed para ilustrar el uso de las expresiones regulares pero sed tiene muchas más posibilidades que aún no hemos comentado. Comentaremos solo algo más pero sin extendernos demasiado. En sed se pueden especificar varias instrucciones separando con ';' cada una de ellas o usando la opción -e antes de cada instrucción. También podemos aprovechar el segundo introductor de la shell.

$ sed "s/otra/vez/g ; s/vez/pez/g" prueba-sed.txt

Hola este es un fichero con datos de prueba
Hola pez pez.
Hola pez pez.
Hola pez pez.
Hola pez pez y pez y pez y pez y pez y pez.
Fin de los datos de prueba

# Idéntico resultado podríamos haber conseguido usando
$ sed -e "s/otra/vez/g" -e "s/vez/pez/g" prueba-sed.txt
# Una tercera forma para conseguir lo mismo
$ sed "
< s/otra/vez/g
< s/vez/pez/g
< " prueba-sed.txt

Por último podemos obtener el mismo resultado usando la opción -f y un fichero de instrucciones para 'sed'.

$ cat  < prueba-sed.sed
< s/otra/vez/g
< s/vez/pez/g
FIN
$ sed -f prueba-sed.sed prueba-sed.txt

Existen posibilidades más avanzadas para usar 'sed' pero con lo que hemos mencionado se pueden hacer muchas cosas.

Podemos eliminar los blancos a principio y al final de linea así como sustituir mas de un blanco seguido por un solo blanco.

$ cat  < trim.sed
< s/^ *//g
< s/ *$//g
< s/ */ /g
< FIN


 
 

Ip Pública 3.144.93.73
Navegador Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)
País United States
Ciudad