Esta página puede ser redistribuida libremente bajo los términos de la licencia GPL. Vease ( GPL texto original ) o si lo prefiere (Traducción española no oficial de la GPL) Al margen de las obligaciones legales que se derivan del uso de esta licencia rogamos sea respetada la referencia a su lugar de publicación original www.ciberdroide.com. y a su autor original Antonio Castro Snurmacher (Madrid 01/01/2000). |
Esta ausencia de garantía se hace extensa a cualquier tipo de uso de este material y muy especialmente a las prácticas, ejercicios, y de ejemplos que encuentre en estas páginas. Deberá trabajar siempre salvo indicación contraria con un SO Linux y con un usario distinto de 'root' sin privilegios especiales. Como directorio de trabajo se procurará usar el directorio '/tmp' o algún otro que no contenga información valiosa. Tampoco se considera buena idea practicar en una máquina que contenga información valiosa. Todo esto son recomendaciones de prudencia. En cualquier caso si algo sale mal toda la responsabilidad será únicamente suya. En ningún caso podrá reclamar a nadie por daños y perjuicios derivados del uso de este material. Para más información lea el contenido de la licencia GPL y abstengase de hacer prácticas si no está dispuesto a asumir toda la responsabilidad.
|
Introducción
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.
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' *
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 |
| |
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. |
| |
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'. |
| |
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'. |
| |
Ejemplo para el operador '|' con el patrón 'ab|cd' Este patrón localizará las cadenas de caracteres que contengan 'ab', 'cd', o '123' |
| |
Ejemplo para el operador '^' con el patrón '^abc' Este patrón localizará las lineas que empiecen por 'abc'. |
| |
Ejemplo para el operador '$' con el patrón 'abc$' Este patrón localizará las lineas que terminen por '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'. |
| |
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'. |
| |
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'. |
| |
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'. |
| |
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'. |
|
Ampliando conocimientos sobre 'egrep'
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'
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.
Ahora usamos el operador '&'. Observe como se sustituye por
el patrón reconocido.
Después eliminamos la secuencia numérica.
Vamos a comprobar que en las expresiones regulares
se intenta siempre reconocer la secuencia más larga
posible.
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.
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.
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.
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.
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.
$ echo "abc1234def" | sed "s/[0-9][0-9]*/NUMERO/"
abcNUMEROdef
$ echo "abc1234def" | sed "s/[0-9][0-9]*/<&>/"
abc<1234>def
$ echo "abc1234def" | sed "s/[0-9][0-9]*//"
abcdef
$ echo "000x111x222x333" | sed "s/x.*x/<&>/"
000<x111x222x>333
# Creamos un ficherito de prueba
$ cat <<FIN > 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
$ 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
$ 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