Aprendiendo Expresiones Regularse Con Grep

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 8

Tabla de contenidos

1. Introduccin
1.1. Sobre este tutorial
1.2. Qu es una expresin regular?
1.3. grep
1.4. Entrecomillando los patrones
2. Expresiones regulares
2.1. 'carcter'
2.2. Barra invertida
2.3. Punto
2.4. \<\>
2.5. * (Repitiendo patrones)
2.6. Rango de carcteres []
2.7. Parntesis \(\)
2.8. Eligiendo el nmero de repeticiones \{\}
2.9. ^ $
1. Introduccin
1.1. Sobre este tutorial
Este tutorial asume cierta familiaridad con la lnea de comandos y bash, si bien no es necesario saber hacer scripts
en bash para seguir el tutorial con normalidad ayudar a entender un poco ciertas partes que se expliquen.
El presente tutorial se ha hecho de tal modo que se aprenda practicando y viendo ejemplos de expresiones regulares
ya hechas, por ello las explicaciones de cada metacarcter se reducen a lo imprescindible, a partir del punto 2 todos
los ejemplos estn hechos de forma que pueda copiar y pegarlos en su terminal para comprobar que funcionan,
hacerles modificaciones al texto o a la expresin regular y as saber si ha comprendido los conceptos.
1.2. Qu es una expresin regular?
Si le digo que una expresin regular es un metalenguaje para expresar el conjunto de palabras aceptadas por los
autmatas finitos, a menos que haya estudiado teora de autmatas puede que no le diga mucho, pero si le digo que
con una expresin regular puede encontrar todas las direcciones de email que hay en un texto cualquiera de forma
automtica puede que le empiece a interesar.
Como definicin prctica podramos decir que una expresin regular es un buscador de patrones, esto es, para
cualquier patrn que defina (recuerde el ejemplo del email) la expresin regular buscar todas las coincidencias.
Como puntualizacin habra que aadir que las expresiones regulares buscarn coincidencias por lneas, esto es que
la coincidencia de un patrn en el texto tiene que encontrarse en su totalidad en la misma lnea.
Ej:
grep 'hola que tal' archivo
Buscar todos los 'hola que tal' (sin comillas) que aparezcan en el texto en la misma lnea, esto es:
Encontrar:
hola que tal ests hoy
Pero no encontrar:
hola
que tal ests hoy
1.3. grep
En este tutorial usaremos la herramienta grep, includa en cualquier instalacin de Debian.
El nombre grep viene de un comando del editor de textos ed (g/re/p), cuyo significado es g: global (en todo el texto),
re: regular expression (buscar la expresin regular), p:print (e imprimirla). Y eso es lo que hace justamente grep.
Opciones de grep:
grep tiene muchas opciones, para ms informacin consultar el manual:
man grep
En este tutorial slo veremos algunas, que son las que nos servirn para aprender a usar las expresiones regulares:
-G o --basic-regexp : Interpreta el patrn como una expresin regular bsica (las que aprenderemos en
este tutorial).
Al ser este el comportamiento por defecto de grep, no se usar.
-v o --invert-match : Invierte el sentido de bsqueda, es decir, busca todo lo que no coincida con el patrn
dado.
-o o --only-matching : Por defecto grep imprime la lnea entera de la coincidencia encontrada, con
esta opcin imprimira slo la coincidencia.
La entrada de texto de grep puede hacerse de dos maneras, dndole el nombre de un fichero, con lo que grep
buscara coincidencias en ese fichero; o introduciendo texto por la entrada estndar (o redirigiendolo).
Ejemplo:
grep 'regex' archivo
Donde regex es el patrn a buscar y archivo el archivo en el que se buscar.
grep 'regex'
Ahora se nos abrira un prompt para introducir texto
echo "regex" | grep 'regex'
Redirigiendo la salida del comando echo para usarla como entrada de grep.
Para una mejor visualizacin de las coincidencias encontradas aada, si no lo tiene ya, la siguiente lnea a su
bashrc o bash_aliases:
alias grep='grep --color=auto'
Si no sabe cmo, copie y pegue lo siguiente en su terminal:
echo 'alias grep="grep --color=auto"' >> ~/.bashrc; source ~/.bashrc
Los comandos anteriores slo hace falta introducirlos una vez, con ellos aadir color a las coincidencias de grep
para la presente terminal y todas las que abra posteriormente.
1.4. Entrecomillando los patrones
Como norma general entrecomillaremos los patrones que le pasemos a grep usando comillas simples, esto es as
debido a que bash realiza sustituciones en determinados carcteres que tienen significado especial para l, son los
llamados "wildcards".
Apuntes de bash (se los puede saltar si sabe bash):
Wildcards:
Estos smbolos en concreto tienen significado especial, y bash los sustituye
antes de pasrselo al comando:
* -> cero o ms carcteres (cualquier carcter).
? -> exactamente un carcter (cualquier carcter).
[abcde]-> exactamente uno de los carcteres entre los corchetes.
[a-o] -> exactamente uno de los carcteres en el rango. -> a, e, i, o en este
caso
[!abcde] -> cualquier carcter que no est entre los corchetes.
[!a-e] -> cualquier carcter que no est en el rango.
{debian,linux} -> alguna de las palabras que estn entre las llaves.
Comillas simples vs comillas dobles:
Las comillas simples, o comillas fuertes, hacen que cualquier smbolo que est
entrecomillado no tenga significado especial, es decir, todo se enva
al comando tal cual se ha puesto.
Las comillas dobles, o comillas dbiles, no interpretan las "wildcards", pero s
la expansin de variable, las de comandos y los escapados, es decir, interpreta
los smbolos: $ ` \
Ej:
rm * #Borra todo, ya que '*' coincide con todas las cadenas.
rm *.jpeg #Borra todos los ficheros que acaben en '.jpeg'.
rm file?.txt #Borra todos los ficheros que empiecen por 'file', tengan un
carcter y acaben en '.txt'
echo '$HOME' #Escribe la palabra '$HOME' en la pantalla (sin las comillas).
echo "$HOME" #Escribe el nombre de su directorio de usuario, ya que interpreta lo
que hay entre comillas.
rm "mi fichero" #Borra un fichero llamado "mi fichero" (sin las comillas), si
existen.
rm mi fichero #Borra un fichero llamado "mi" y un fichero llamado "fichero", si
existen.
No hay que confundir los patrones de sustitucin de bash con expresiones regulares.
Y las variables?
Si quiere usar el valor de una variable dentro de una expresin regular hay que encerrarla entre comillas dobles.
Ejemplo:
variable='hola'
grep 'regex'"$variable"'regex' archivo
Ya que la concatenacin de cadenas de texto en bash se hace ponindolas juntas.
2. Expresiones regulares
2.1. 'carcter'
La expresin regular ms sencilla que se puede crear es la compuesta por un carcter o por un conjunto de
carcteres (palabra).
Ej:
grep 'hola' archivo # Busca 'hola' en archivo
grep 'a' archivo # Busca 'a' en archivo
grep 'bienvenido al tutorial' archivo # Busca 'bienvenido al tutorial' en archivo
2.2. Barra invertida
En las expresiones regulares, las barras invertidas "\" normalmente quitan el significado especial de algn carcter,
aunque algunas veces se lo den, esto puede ser un poco complicado al principio pero se acabar acostumbrando.
Como norma general, cualquier carcter con un significado especial que vea en este tutorialestar en la forma en la
que tenga el significado especial, para quitarle ese significado no tiene ms que quitarle la barra si la tiene o
ponrsela si no la tiene.
Normalmente a los carcteres precedidos por barra invertida y que sin ella tendran significado especial, se llaman
escapados.
2.3. Punto
El carcter punto "." se sustituye en una expresin regular por cualquier carcter, excepto nueva lnea.
Ejemplos:
echo 'a b' | grep -o '.'
grep encontrar como coincidencias: "a" y "b"
echo 'a b . ;' | grep -o '.'
grep encontrar como coincidencias: "a", "b", "." y ";".
echo 'a b . ;' | grep -o '\.'
grep slo encontrar como coincidencia: ".", ya que al escapar el patrn ha hecho que este pierda su significado de
cualquier carcter, a tener el significado de: el carcter punto.
quien=tu
echo 'en un'"$quien"' mi' | grep -o '..'
grep encontrar como coincidencias: "en", "un", "tu" y "mi"
echo ';:a una ala uno' | grep -o '..a'
grep encontrar como coincidencias: ";:a", "una", "ala", pero no "uno" ya que no coincide con el patrn cualquier
palabra de tres carcteres siendo el ltimo la "a"
Ntese que con palabra nos referimos a cualquier concatenacin de carcteres
echo 'vuela miedo fuera' | grep -o '..e.a'
grep encontrar como coincidencias: "vuela", "fuera", pero no "miedo" ya que aunque cumple la parte del patrn
"..e." no cumple lo de acabar en a.
echo 'Este tutorial de grep me gusta mucho' | grep -o '.e'
Al contrario de lo que se podra esperar no slo ha encontrado las coincidencias: "de" y "me".
El resultado es cuando menos extrao, si se ha usado la opcin -o como en este ejemplo se obtendrn trozos de
palabra, en concreto los trozos que concuerdan con el patrn, sin la opcin -o y con el coloreado de grep activado se
observar mejor y se podrn inferir las razones.
Lo que ha ocurrido ha sido porque la expresin regular buscaba patrones que coincidieran con ".e" includos los que
estuviesen dentro de otras palabras, entonces cmo buscamos nicamente por las palabras que coincidan con
".e"?
Una posible solucin sera aadir espacios a los dos lados del patrn:
echo 'Este tutorial de grep me gusta mucho' | grep -o ' .e '
Esto solucionara el problema con esta cadena de texto, pero y si una de las palabras que queremos encontrar con
el patrn estn al principio o al final de la lnea?, en ese caso los espacios seran un problema ya que pueden faltar.
La solucin est en usar otro de los meta-carcteres de las expresiones regulares: \<\>
2.4. \<\>
El metacarcter \<\> hace que todos los patrones dentro de l slo coincidan con palabras enteras, esto es,
palabras separadas entre s por espacios. Para este metacarcter los smbolos de puntuacin (.,< etc...) no forman
parte de la palabra.
echo 'Este tutorial de grep me gusta mucho' | grep -o '\<..\>'
grep encontrar como coincidencias: "de" y "me", ya que son las nicas palabras enteras que coinciden con el
patrn.
echo 'Ya hemos aprendido algunas cosas' | grep -o '\<....s\>'
grep encontrar como coincidencias: "hemos" y "cosas"
echo 'Ya hemos aprendido algunas cosas' | grep '\<.a\>'
grep encontrar como coincidencia: "Ya", sin embargo si no hubiesemos puesto \<\> entonces el patrn habra
coincidido tambin con: " a", "na", "sa". La coincidencia con " a" es debida a que como se explic antes, el punto
es sustituido por cualquier carcter exceptuando nueva lnea.
echo '<>' | grep '<..'
grep encontrar como coincidencia: "<echo '<>' | grep '\<..'
grep encontrar como coincidencias: "Ya", "he", "ap", "al", "co", esto es, el principio de cada palabra que encaje con
el patrn. Por lo tanto \> har lo contrario. Veamoslo en un ejemplo.
echo '<>' | grep '..\>'
grep encontrar como coincidencias: "Ya", "os", "do", "as", "as", o lo que es lo mismo el final de las palabras que
encajan con el patrn.
2.5. * (Repitiendo patrones)
Todos los metacarcteres anteriores estn muy bien si sabe exctamente cuntos carcteres tiene la palabra que
quiere buscar, pero qu ocurre si no lo sabe?, pues que habr que usar el metacarcter *, * repetir el patrn que
le precede cero o ms veces.
echo '4 44 444 444 4444 44444' | grep '4*'
grep encontrar como coincidencias todos y cada uno de los nmeros que contengan cuatros.
echo '4 454 4554554 455545554 4555455545554 44444' | grep '4*'
grep encontrar como coincidencias todos y cada uno de los nmeros que contengan cuatros.
echo '4 454 4554554 455545554 4555455545554 44444' | grep '.*'
grep encontrar como coincidencias todos, ya que el punto se traduce como cualquier carcter y * (repetido cero o
ms veces).
echo '.* 44 58.* hhial' | grep '\.\*'
grep encontrar como coincidencias: ".*" debido a que los carcteres estn escapados.
echo '4 454 4554554 455545554 4555455545554 44444' | grep '\<4*\>'
grep encontrar como coincidencias slo los nmeros que contengan nicamente cuatros.
Pero hay que tener cuidado con *, ya que como dice la definicin "repetir el patrn que le precede cero o ms
veces."
Todava no ve el peligro?, vemoslo con un ejemplo.
echo -e "Lnea sin comentario\n#Lnea con comentario\nLnea sin comentario" | grep
'#*'
echo -e interpreta "\n" como nueva lnea, es decir, sera como escribir la frase hasta "\n" darle al retorno de carro
(enter, nueva lnea) continuar escribiendo y repetir lo anterior
Con ste patrn debera encontrar las lneas que tengan algn comentario, o no?. Como poda esperar tras toda la
preparacin anterior: no, pero lo importante es el por qu; esto ha ocurrido porque como se mencion anteriormente *
repeta el patrn anterior cero o ms veces, o lo que es lo mismo, se buscaran todas las lneas tuvieran o no #.
Para solucionar este problema no habra ms que aadir otro # antes del que precede al *:
echo -e "Lnea sin comentario\n#Lnea con comentario\nLnea sin comentario" | grep
'##*'
esto buscar todas las lneas que tengan uno o ms # debido a que el metacarcter slo se aplica al patrn que le
precede, esto es, el segundo #.
2.6. Rango de carcteres []
Gracias al metacarcter [], se pueden elegir diferentes carcteres a los cules aplicarles algn otro patrn de
sustitucin.
echo '5895 589435 539853 54849' | grep -o '[0123456789]*'
grep encontrara como coincidencias a todos los conjuntos numricos, ya que es lo que le hemos indicado con el
conjunto de carcteres encerrados entre corchetes.
echo 'hola hhaif aieo uuieo' | grep -o '\<[aeiou]*\>'
grep encontrara como coincidencias a todos los grupos de vocales: "aieo", "uuieo"
En estos casos tambin se pueden indicar rangos, por ejemplo, para que coincida con cualquier nmero se puede
poner de la siguiente manera: [0-9], ntese que se empieza en cero; para indicar cualquier letra (del abecedario
ingls) minscula se puede hacer [a-z], y maysculas: [A-Z], tambin se pueden combinar: [a-zA-Z] coincidira con
cualquier letra, mayscula o minscula.
echo 'hola hhaif AiEo uu66ieo' | grep -o '\<[A-Za-z]*\>'
grep encontrara como coincidencias todas las palabras que slo contengan letras alfabticas (inglesas).
echo 'hola hhAIf AiEo uu66ieo' | grep -o '\<[AIa-z]*\>'
grep encontrara como coincidencias todas las palabras que slo contengan letras alfabticas minsculas
(cualquiera) y las letras maysculas A e I.
Al utilizarse el guin para indicar rangos, si queremos usarlo como carcter en el grupo debemos ponerlo al principio
o al final, y cualquier metacarcter debe ir escapado.
echo 'hola hh-AIf A-iEo u.u66ieo' | grep '[AIa-z\.-]*'
grep encontrara como coincidencias todas las palabras o subpalabras que slo contengan letras alfabticas
minsculas (cualquiera) y A e I, adems de los smbolos "." y "-".
echo 'hola hh-AIf A-iEo u.u66ieo' | grep -o '\<[AIa-z\.-]*\>'
en este caso, con la idea de que coincida cualquier palabra que contenga el conjunto antes mencionado, se ha
usado el metacarcter \<\>, pero el resultado no ha sido el esperado, y su explicacin es que el metacarcter
anterior sirve para coincidir con palabras que no contengan smbolos de puntuacin o guiones.
Cabe destacar que existen conjuntos de carcteres POSIX definidos para aadir portabilidad, son los siguientes:
[:alnum:]Alfanumricos
[:alpha:]Carcteres alfabticos
[:upper:]Carcteres en mayscula
[:lower:]Carcteres en minscula
[:digit:]Dgitos
[:print:]Carcteres imprimibles
hay algunos ms, pero estos son los ms importantes
Ahora reescribiremos algunos ejemplos anteriores usando estos conjuntos POSIX:
echo '5895 589435 539853 54849' | grep -o '[[:digit:]]*'
Ntese el uso del doble corchete.
echo 'hola hhaif AiEo uu66ieo' | grep -o '\<[[:alpha:]]*\>'
grep encontrara como coincidencias todas las palabras que slo contengan letras alfabticas (inglesas).
Tambin se puede elegir el complementario de un conjunto, esto es, los carcteres que no estn en el conjunto.
Esto lo haremos con [^conjunto].
echo 'hola 6g hhaif 5345235 AiEo 66' | grep -o '\<[^[:alpha:]]*\>'
grep encontrar como coincidencias todas las palabras que no contengan letras alfabticas (inglesas).
echo 'hola hh-AIf EEE5 A-iEo u.u66ieo' | grep -o '\<[^AIh-z]*\>'
grep encontrar como coincidencias todas las palabras que no contengan letras A, I, de h a z.
2.7. Parntesis \(\)
El metacarcter parntesis sirve para seleccionar un patrn al que le aplicaremos un metacarcter modificador, por
ejemplo *; tiene adems un par de carctersticas bastante interesantes que veremos ms adelante.
echo 'holaholaholahola holahola adios' | grep -o '\(hola\)*'
grep encontrara como coincidencias todas las palabras que contengan repeticiones de la palabra hola
echo 'holahelloholahola holahola adios' | grep -o '\<\(hola\)*\>'
grep encontrara como coincidencias todas las palabras que contengan nicamente repeticiones de la palabra hola
Una de las caractersticas interesantes del parntesis que se mencion anteriormente es la de recordar una
coincidencia, esto es, el patrn guardar en un registro numrico (del 1 al 9), cada coincidencia que haya coincidido
con un patrn que se encuentre entre parntesis. Siendo \1 la primera coincidencia recordada, \2 la siguiente, y as
hasta el \9.
echo '6hola6 5hola4 4adios9 7adios7' | grep -o '\<\([0-9]\)[[:alpha:]]*\1\>'
grep encontrar como coincidencias cualquier palabra que empiece con un nmero y acabe con el mismo nmero y
entre los nmeros tenga letras.
echo 'NaN LOL Wow TypeT' | grep -o '\<\([[:upper:]]\)[[:alpha:]]*\1\>'
grep encontrar como coincidencias cualquier palabra que empiece con una letra mayscula y acabe con la misma
letra y entre las letras maysculas tenga letras.
echo '0990 5785 5775 6996 ' | grep -o '\([[:digit:]]\)\([[:digit:]]\)\2\1'
grep encontrar como coincidencias cualquier nmero capica de cuatro cifras.
La otra caracterstica interesante es la de poder elegir entre dos patrones distintos usando \| entre los dos patrones:
echo 'ftp://asdfasf.com http://asfasdf.com' | grep -o '\(ftp\|http\)://[a-z]*\.com'
grep encontrar como coincidencias cualquier palabra que empiece con ftp o http y que contine con un conjunto de
letras minsculas y acabe en .com
echo 'ftp://ulises.hostalia.com/debian http://ftp.es.debian.org/debian/' | grep -o
'\(ftp\|http\)://[a-z\.-\/]*'
grep encontrar como coincidencias cualquier palabra que empiece con ftp o http y que contine con un conjunto de
letras minsculas, puntos, y guiones.
echo 'Yes No S No' | grep -o '\(S\|Yes\)'
grep encontrar como coincidencias: "S" y "Yes".
echo '6hola6 9hola9 5jaja4 5haha5' | grep '\(6\|9\)[[:alpha:]]*\1'
grep encontrar como coincidencias cualquier palabra que empiece con 6 o 9 y que acabe con el mismo nmero,
con letras en medio.
2.8. Eligiendo el nmero de repeticiones \{\}
Con los metacarcteres \{\}, poniendo un nmero o dos entre las llaves se puede elegir el nmero de veces que
queremos que se repita un patrn.
echo '555 555555 555555 5555555 55 5555' | grep -o '\<5\{6\}\>'
grep encontrara las palabras formadas por exctamente seis cincos.
echo '555 555555 555555 5555555 55 5555' | grep '\<5\{3,6\}\>'
grep encontrar las palabras formadas por entre tres y seis cincos.
Tambin las podemos mezclar con otros metacarcteres
echo '555 asd#lha sdf 55hi5 555aASasd55 55 5555' | grep -o '.\{4,11\}'
grep encontrar como coincidencias cualquier palabra con entre 4 y 11 carcteres, el resultado puede parecer raro,
pero la explicacin es sencilla: el metacarcter "." significa cualquier carcter, incluido el espacio, y grep tiende a
buscar la palabra ms grande que se adapte al patrn.
As que para conseguir el efecto deseado:
echo '555 asd#lha sdf 55hi5 555aASasd55 55 5555' | grep -o '[[:alnum:]#]\{4,11\}'
Por si lo estaba pensando, con \<\> y el punto tampoco conseguira el resultado que se buscaba, ya que el punto
seguira significando cualquier carcter incluido el espacio, comprubelo usted mismo.
echo 'http://www.esdebian.org/que-haces https://encrypted.google.com/' | grep -o
'https\{0,1\}[[:alnum:]:\/_-.]*'
Como habr podido comprobar el metacarcter \{\} slo afecta al elemento ms cercano a l, entonces, cmo
aplicarselo a un grupo?. Fcil con \(\).
echo 'http://www.esdebian.org/que-haces www.esdebian.org/que-haces' | grep -o '\
(http://\)\{0,1\}[[:alnum:]\/_-.]*'
2.9. ^ $
Los ltimos metacarcteres de este tutorial son ^ y $, estos dos metacarcteres sirven para buscar coincidencias al
principio y al final de una lnea respectivamente.
echo 'hola hola hola' | grep '^hola'
grep slo coincidir con el primer hola, debido a que es el que est al principio de la lnea.
echo 'adios adios adios' | grep 'adios$'
grep slo coincidir con el ltimo adios, debido a que es el que est al final de la lnea.
echo -e "Este es el final del tutorial,\nesperamos que lo haya disfrutado y haya
aprendido mucho sobre las expresiones regulares.\nesDebian" | grep '^[[:alpha:]]*$'

También podría gustarte