Las Expresiones Regulares, o Regular Expressions (RegEx), son patrones que podemos usar para encontrar una determinada combinación de caracteres dentro de un texto. Las RegEx proporcionan una manera muy flexible y poderosa de buscar o reconocer cadenas de texto para luego imprimirlas, modificarlas o cambiar su formato.
Existen dos tipos de RegEx en el estándar POSIX: Basic Regular Expressions (BRE) y Extended Regular Expressions (ERE). Luego están las Perl Compatible Regular Expression (PCRE), escritas en Lenguaje C e inspiradas en el poder de Perl.
No debemos confundir RegEx con Shell Globbs, ya que éste ultimo trabaja solamente con nombres de archivos. Las RegEx fueron definidas en la década del 1950 y tienen su origen en Regular Events, una notación creada por Stephen C. Kleene, un matemático estadounidense.
Los lenguajes de programación más conocidos soportan RegEx: C, Ruby, XML, Visual Basic, Unix Shell, Java, JavaScript, Python y, por supuesto, Perl.
De ahora en adelante nos enfocaremos en el uso de RegEx en el Linux Shell (Bash) usando grep, sed y awk. Nuestra guía y referencia de estudio es este cheatsheet (chuleta, en español) y como texto objetivo usaremos el poema Hay Un País en el Mundo, del poeta nacional (dominicano) Pedro Mir (1913-2000).
Este comando debe su existencia Ken Thompson, y su nombre en sí mismo una RegEx: g/re/p (globally search for a regular expression and print matching lines) es la herramienta para filtrado de texto por excelencia en entornos Unix/Linux. De hecho el Diccionario Oxford tiene una entrada de grep como verbo, debido a esto es posible decir "I'm going to grep my files".
Manos a la obra...
Cada idioma tiene sus signos y reglas de acentuación para darle sentido, la escritura y el sonido adecuado a las palabras. Por lo que en español no es lo mismo "pais" que "país":
$ grep "pais" hay-un-pais-en-el-mundo.txt y mártir de los tórridos paisajes
$ grep "país" hay-un-pais-en-el-mundo.txt Hay un país en el mundo un país en el mundo que en este fluvial país en que la tierra brota, un país en el mundo Es un país pequeño y agredido. Sencillamente triste, vengo a hablar de un país. Desterrado en su tierra. y un país,Agregando la opción -n, grep nos muestra el número de la línea que coincidió con el patrón:
$ grep -n "país" hay-un-pais-en-el-mundo.txt 1:Hay un país en el mundo 48:un país en el mundo 52:que en este fluvial país en que la tierra brota, 90:un país en el mundo 99:Es un país pequeño y agredido. Sencillamente triste, 104:vengo a hablar de un país. 163:Desterrado en su tierra. y un país,La opción -c, no imprime las líneas que coinciden pero sí la suma total de ellas:
$ grep -c "país" hay-un-pais-en-el-mundo.txt 7En Linux has oído hablar de Case Sensitive. Eso significa que Donde y donde no es lo mismo para grep.
$ grep "Donde" hay-un-pais-en-el-mundo.txt Donde un ángel respira.
$ grep "donde" hay-un-pais-en-el-mundo.txt donde el día tiene su triunfo verdadero, donde quiera, donde ruedan montañas por los valles como frescas monedas azules, donde duerme de donde el viento asalta el íntimo terrón donde cada colina parece un corazón, donde un campesino breve, final de viaje donde una isla y abrid los ojos donde un desastre abre una herida donde unos ojos no tienen sexo donde una patria donde el hombre y la res y el surco duermen donde ardePara obtener ambos resultados usamos la opción -i (case insensitive):
$ grep -i "donde" hay-un-pais-en-el-mundo.txt donde el día tiene su triunfo verdadero, donde quiera, donde ruedan montañas por los valles como frescas monedas azules, donde duerme de donde el viento asalta el íntimo terrón donde cada colina parece un corazón, donde un campesino breve, final de viaje donde una isla y abrid los ojos donde un desastre abre una herida donde unos ojos no tienen sexo donde una patria donde el hombre y la res y el surco duermen Donde un ángel respira. donde ardePor defecto grep imprime todas las líneas que contienen el patrón que buscamos:
$ grep "Pero" hay-un-pais-en-el-mundo.txt Pero no. Pero no. Pero no. Pero Pero ebrio de orégano y de anís,Usaremos la opción -x para que solo nos muestre las líneas que son el patrón exactamente:
$ grep -x "Pero" hay-un-pais-en-el-mundo.txt PeroExiste el término "inverted match", consiste en imprimir las excepciones al patrón de búsqueda, usando la opción -v:
$ grep -v "Pedro" hay-un-pais-en-el-mundo.txtEl comando anterior imprimirá todo el contenido del fichero "hay-un-pais-en-el-mundo.txt" excepto la última línea que contiene el patrón de búsqueda "Pedro".
Podemos usar una RegEx para imprimir las líneas que terminan en "tierra.". El carácter especial "$" indica final de la línea.
$ grep "tierra.$" hay-un-pais-en-el-mundo.txt los campesinos no tienen tierra. los campesinos no tienen tierra. los campesinos no tienen tierra. los campesinos no tienen tierra. no tienen tierra no tienen tierra. Traficante de tierras y sin tierra.Para usar RegEx en el comando grep es necesario usar la opción -E, de Extended Regular Expressions. Para imprimir las líneas que tienen la palabra "piedra" o la palabra "palma":
$ grep -E 'piedra|palma' hay-un-pais-en-el-mundo.txt que se detiene junto a una piedra de constructiva paz en cada palma.La siguiente RegEx imprime las palabras de tres letras con la primera en mayúscula:
$ grep -E '[A-Z]{1}\w{2}\b' hay-un-pais-en-el-mundo.txt Hay un país en el mundo Con tres millones Hay Hay Los que la roban no tienen ángeles Pedro Mir (1913-2000).Esta RegEx imprime las palabras de trece letras que comienzan con mayúscula, además con la opción -o solo muestra el patrón que coincide sin el resto del texto que compone la línea:
$ grep -o -E '[A-Z]\w{12}\b' hay-un-pais-en-el-mundo.txt Sencillamente Sencillamente Sencillamente Sencillamente Sencillamente Sencillamente
En el siguiente comando tenemos una RegEx que va a encontrar cualquier secuencia de 4 dígitos, un guión, seguido por cuatro dígitos.
$ grep -E '([0-9]{4}-[0-9]{4})' hay-un-pais-en-el-mundo.txt Pedro Mir (1913-2000).
Pero, si se dieron cuenta, aunque la RegEx tiene los paréntesis, grep no los marcó como resultado de la búsqueda. Esto se debe a que los paréntesis son caracteres especiales en RegEx que sirven para agrupar expresiones. Si deseamos que sean parte del patrón de búsqueda es necesario "escaparlos" usando "\".
$ grep -E '\([0-9]{4}-[0-9]{4}\)' hay-un-pais-en-el-mundo.txt Pedro Mir (1913-2000).grep puede recibir entrada y enviar su salida desde y hacia otros comandos usando pipes o tuberías. Para profundizar más sobre el comando grep puedes consultar su manual:
$ man grep
No hay comentarios:
Publicar un comentario