1. Describir formas
Una expresión regular es un patrón que describe un conjunto de textos. Un texto coincide con la expresión si tiene la forma descrita.
El nombre se abrevia de muchas maneras: regex, regexp, «expresión». La idea se entiende con un ejemplo. Estas tres líneas son textos distintos, y tienen la misma forma: cuatro dígitos, un guion, dos dígitos, un guion, dos dígitos.
2026-10-01
1999-12-31
2031-07-15
Una expresión regular permite decir exactamente eso, y con ella un programa puede encontrar todas las fechas de un archivo sin conocer ninguna de antemano:
^[0-9]{4}-[0-9]{2}, pieza por pieza. Una expresión regular se lee de izquierda a derecha, como una lista de condiciones.Para practicar usaremos grep con dos opciones, y conviene fijarlas desde ahora:
| Opción | Para qué la usamos |
|---|---|
-E | Activa la sintaxis extendida, la más cómoda. La diferencia con la básica está en la sección 9. |
-o | Muestra solo lo que coincidió. Es la mejor manera de ver qué describe una expresión. |
Las expresiones se escriben siempre entre comillas simples. Usan casi todos los caracteres que la shell interpreta —asteriscos, signos de dólar, corchetes, barras— y hay que impedir que los toque, como aprendimos en el tema 9.
2. Las piezas del lenguaje
Dentro de una expresión hay dos clases de caracteres. La mayoría son literales: una a coincide con una «a», un 7 con un «7». Unos pocos son metacaracteres: no valen por sí mismos, sino que significan algo. Toda la sintaxis son estos, agrupados en cuatro familias:
| Familia | Responde a | Símbolos |
|---|---|---|
| Clases | ¿Qué carácter? | . [ ] [^ ] |
| Anclas | ¿En qué lugar? | ^ $ \b |
| Cuantificadores | ¿Cuántas veces? | * + ? { } |
| Estructura | ¿Qué va junto, y qué alternativas hay? | ( ) | |
A estos se suma la barra invertida, \, que quita o da significado al carácter siguiente. Las secciones que siguen recorren las familias en ese orden.
Una regla general, que ya vimos con grep: por defecto una expresión puede coincidir en cualquier parte de la línea. No hace falta que describa la línea entera; alcanza con que alguna porción de la línea tenga esa forma.
3. El punto: un carácter cualquiera
El punto coincide con exactamente un carácter, el que sea: una letra, un dígito, un espacio, un signo.
$ cd ~/practica
$ grep 'l.z' tareas.txt # una l, un carácter cualquiera, una z
Pagar la luz
$ grep -o 'm..' ventas.csv | sort -u # una m y los dos caracteres siguientes
mon
mou
Cada punto ocupa una posición: m.. tiene tres caracteres de largo, ni más ni menos. Coincidió con el comienzo de «monitor» y de «mouse».
El punto es el metacarácter que más errores produce, por una razón simple: se lo escribe sin querer. Al buscar notas.txt o 192.168.1.1, los puntos están actuando como «cualquier carácter», y la búsqueda acepta más de lo debido. Lo vimos en el tema anterior, y la solución está en la sección 10.
4. Clases: uno de estos caracteres
Los corchetes describen también un solo carácter, pero limitado a un conjunto. Son los mismos de los comodines de la shell, con una diferencia en la negación:
| Expresión | Coincide con un carácter que… |
|---|---|
[abc] | Sea una a, una b o una c. |
[a-z] | Sea una minúscula. |
[A-Za-z] | Sea una letra, sin ñ ni tildes. |
[0-9] | Sea un dígito. |
[^0-9] | No sea un dígito. El circunflejo, al comienzo de los corchetes, niega. |
[^,] | No sea una coma. |
$ grep -c '[MS]a' ventas.csv # «Ma» o «Sa»: Marta o Salta
5
$ grep -c '0[56],' ventas.csv # un 0, un 5 o un 6, y una coma: los días 5 y 6
4
Para los conjuntos de uso frecuente existen las clases con nombre, que conocimos en el tema 9 y que tienen en cuenta el idioma: incluyen la ñ y las vocales acentuadas. Se escriben dentro de unos corchetes, de ahí la doble pareja:
| Clase | Contiene | Abreviatura en muchas herramientas |
|---|---|---|
[[:digit:]] | Los dígitos. | \d, pero no en grep -E |
[[:alpha:]] | Las letras. | — |
[[:alnum:]] | Letras y dígitos. | — |
[[:upper:]], [[:lower:]] | Mayúsculas; minúsculas. | — |
[[:space:]] | Espacios, tabulaciones y saltos de línea. | \s |
[[:punct:]] | Signos de puntuación. | — |
[[:alnum:]_] | Los caracteres «de palabra»: letras, dígitos y guion bajo. | \w |
Dentro de los corchetes casi todos los metacaracteres pierden su significado: [.*] coincide con un punto o un asterisco literales. Los únicos que conservan un papel son el circunflejo inicial, que niega; el guion entre dos caracteres, que forma un rango; y el corchete de cierre.
La clase negada [^,], «cualquier cosa menos una coma», es la pieza más útil para trabajar con archivos de campos. Vuelve a aparecer en casi todas las secciones siguientes.
5. Anclas: dónde debe estar
Las anclas no coinciden con ningún carácter. Coinciden con una posición, y sirven para exigir que el resto de la expresión esté en un lugar determinado de la línea.
| Ancla | Posición | Ejemplo | Coincide con |
|---|---|---|---|
^ | El comienzo de la línea. | ^# | Las líneas que empiezan con #. |
$ | El final de la línea. | bash$ | Las líneas que terminan en «bash». |
^…$ | La línea entera. | ^$ | Las líneas vacías. |
\b | El borde de una palabra. | \bla\b | «la» como palabra, no dentro de «plantas». |
$ grep '^P' tareas.txt # empieza con P
Pagar la luz
$ grep 's$' tareas.txt # termina en s
Llamar a Luis
Regar las plantas
$ grep -c '^2026-10-0[12]' ventas.csv # la fecha, al comienzo, es del día 1 o 2
4
$ grep -c 'nologin$' /etc/passwd # cuentas cuya shell es nologin
38
Las anclas son lo que da precisión. En el tema 27, grep 10 ventas.csv coincidía con todas las líneas por culpa de las fechas. Con un ancla se dice dónde se quiere el número: ,10$ sería «un 10 como último campo».
El circunflejo tiene dos significados, y no hay que confundirlos: fuera de los corchetes y al principio es el ancla de comienzo; dentro de los corchetes y al principio es la negación. En ^[^#] aparecen los dos: «una línea que empieza con un carácter que no es #».
Los bordes de palabra se pueden escribir también por separado: \< para el comienzo de una palabra y \> para el final. La opción -w de grep equivale a rodear todo el patrón con \b.
6. Cuantificadores: cuántas veces
Hasta aquí cada pieza ocupaba una posición. Los cuantificadores permiten decir que una pieza se repite.
Un cuantificador indica cuántas veces puede aparecer el elemento que tiene inmediatamente antes. No significa nada por sí solo.
| Cuantificador | El elemento anterior aparece… | Se lee |
|---|---|---|
* | Cero o más veces. | «Los que haya, incluso ninguno.» |
+ | Una o más veces. | «Al menos uno.» |
? | Cero o una vez. | «Opcional.» |
{3} | Exactamente 3 veces. | |
{2,} | 2 veces o más. | |
{2,4} | Entre 2 y 4 veces. |
Se ven bien con un texto de prueba, pasado a grep con una cadena en línea, y la opción -o para mostrar cada coincidencia. El elemento cuantificado es la letra b:
$ grep -oE 'ab*c' <<< 'ac abc abbc abbbc' | paste -s -d' ' # cero o más veces
ac abc abbc abbbc
$ grep -oE 'ab+c' <<< 'ac abc abbc abbbc' | paste -s -d' ' # una o más
abc abbc abbbc
$ grep -oE 'ab?c' <<< 'ac abc abbc abbbc' | paste -s -d' ' # cero o una
ac abc
$ grep -oE 'ab{2,}c' <<< 'ac abc abbc abbbc' | paste -s -d' ' # dos o más
abbc abbbc
La potencia aparece al combinar un cuantificador con una clase. «Un dígito, una o más veces» es un número; «cualquier cosa menos una coma, cero o más veces» es un campo:
$ grep -oE '[0-9]+$' ventas.csv | paste -s -d' ' # el número que hay al final de cada línea
90 320 75 40 45 640 45 16 30 320
$ grep -E ',[0-9]{3}$' ventas.csv # importes de exactamente tres cifras
2026-10-01,Marta,Mendoza,monitor,1,320
2026-10-03,Ana,Mendoza,monitor,2,640
2026-10-06,Luis,Rosario,monitor,1,320
| Expresión | Describe |
|---|---|
[0-9]+ | Un número entero. |
[a-z]+ | Una palabra en minúsculas. |
[^,]* | El contenido de un campo separado por comas. |
.* | Cualquier cosa, de cualquier largo: el «comodín» de las expresiones regulares. |
[[:space:]]+ | Uno o más espacios en blanco. |
La cuarta fila es la más usada, y la más mal usada. .* sirve para decir «y en el medio, lo que sea»: ^Luis.*monitor sería «empieza con Luis y más adelante dice monitor». Su problema es el de la sección siguiente.
7. La codicia
Cuando una expresión puede coincidir de varias maneras, hay una regla que decide:
Los cuantificadores son codiciosos: toman tanto texto como les sea posible, siempre que el resto de la expresión pueda seguir coincidiendo.
Con .*, que acepta cualquier carácter, eso significa llegar hasta lo más lejos que se pueda. Veamos el intento de extraer el primer campo de una línea como «todo, hasta una coma»:
$ head -n 1 ventas.csv | grep -oE '^.*,' # «todo hasta una coma»… la última
2026-10-01,Luis,Rosario,teclado,2,
$ head -n 1 ventas.csv | grep -oE '^[^,]*,' # «lo que no sea coma, y una coma»
2026-10-01,
La primera expresión no se detuvo en la primera coma. El punto acepta también las comas, de modo que .* avanzó hasta el final de la línea, y luego retrocedió lo mínimo necesario para que la coma final de la expresión encontrara con qué coincidir: la última del texto.
La segunda no tiene ese problema, porque [^,] no puede atravesar una coma: se detiene obligadamente en la primera.
Casi todos los resultados inesperados con expresiones regulares vienen de un .* que abarcó de más. La corrección es reemplazarlo por una clase negada que nombre el carácter en el que debe detenerse: [^,]* para un campo, [^"]* para el contenido de unas comillas, [^ ]* para una palabra. Es más preciso, y además más rápido.
8. Alternativa y grupos
La barra vertical separa alternativas: la expresión coincide si coincide cualquiera de ellas. Los paréntesis agrupan, con dos propósitos: limitar el alcance de una alternativa, y hacer que un cuantificador se aplique a varios caracteres en lugar de uno solo.
| Expresión | Coincide con |
|---|---|
mouse|cable | «mouse» o «cable». |
^(Ana|Luis) | «Ana» o «Luis», al comienzo de la línea. |
^Ana|Luis | «Ana» al comienzo, o «Luis» en cualquier parte. Sin paréntesis, la barra separa todo lo que tiene a cada lado. |
(ja)+ | «ja», «jaja», «jajaja»… El + se aplica al grupo entero. |
ja+ | «ja», «jaa», «jaaa»… El + se aplica solo a la a. |
$ grep -cE 'mouse|cable' ventas.csv
5
$ grep -E ',(Ana|Marta),(Salta|Mendoza),' ventas.csv
2026-10-01,Marta,Mendoza,monitor,1,320
2026-10-02,Ana,Salta,mouse,5,75
2026-10-03,Ana,Mendoza,monitor,2,640
2026-10-06,Marta,Mendoza,mouse,2,30
La segunda búsqueda combina dos condiciones sobre dos campos, cosa que en el tema anterior exigía encadenar varios grep. Las comas incluidas en el patrón aseguran que cada nombre ocupe un campo entero.
Un grupo con cuantificador permite contar campos, y con eso llegar a una columna determinada. «Cuatro veces: un campo y su coma» deja la expresión parada al comienzo del quinto campo:
$ grep -E '^([^,]*,){4}10,' ventas.csv
2026-10-02,Luis,Rosario,cable,10,40
Es la respuesta exacta a la pregunta que grep 10 no sabía responder. También es una expresión que ya cuesta leer; para seleccionar por columnas hay una herramienta mejor, awk, en el tema 30.
9. Básicas y extendidas
Hay un tropiezo histórico que conviene conocer antes de encontrarlo. Las herramientas de Unix entienden dos dialectos de expresiones regulares, que difieren en cómo se escriben algunos metacaracteres:
| Básicas (BRE) | Extendidas (ERE) | |
|---|---|---|
| Las usan | grep, sed | grep -E, sed -E, awk |
| Iguales en las dos | . [ ] [^ ] ^ $ * | |
| Una o más veces | \+ | + |
| Opcional | \? | ? |
| Repetición | \{2,4\} | {2,4} |
| Grupo | \( \) | ( ) |
| Alternativa | \| | | |
La regla es simétrica. En el dialecto básico, los signos + ? { } ( ) | son caracteres literales, y se vuelven especiales con una barra invertida delante. En el extendido es al revés: son especiales, y la barra invertida los vuelve literales.
$ grep -c ',[0-9]\{3\}$' ventas.csv # básica
3
$ grep -cE ',[0-9]{3}$' ventas.csv # extendida
3
$ grep -c 'mouse|cable' ventas.csv # básica, sin escapar: busca el texto «mouse|cable»
0
La última línea es el síntoma típico: una expresión correcta que no encuentra nada, porque le falta la -E y sus símbolos se toman al pie de la letra.
La sintaxis extendida es más legible y es la que usan awk y casi todos los lenguajes de programación. Conviene adoptarla como única: grep -E y sed -E, siempre. La básica hay que saber leerla, porque abunda en scripts y en documentación.
10. Escapar: el símbolo como texto
Cuando lo que se busca contiene un metacarácter, hay que quitarle su significado. Se hace anteponiéndole una barra invertida:
| Para buscar… | Se escribe | Sin escapar coincidiría con |
|---|---|---|
| Un punto | \. | Cualquier carácter. |
notas.txt | notas\.txt | También «notas-txt» o «notasXtxt». |
| Un signo de pesos | \$ | El fin de línea. |
| Un asterisco | \* | Una repetición de lo anterior. |
Un paréntesis, con -E | \( | El comienzo de un grupo. |
| Una barra invertida | \\ | — |
$ ls | grep -E '\.txt$' # nombres que terminan en .txt
informe.txt
notas.txt
tareas.txt
Hay tres maneras de buscar un texto con símbolos, y conviene elegir según el caso:
| Recurso | Ejemplo | Cuándo |
|---|---|---|
| Barra invertida | grep '192\.168\.1\.1' | Cuando el resto del patrón sí usa metacaracteres. |
| Corchetes | grep '192[.]168[.]1[.]1' | Lo mismo; dentro de corchetes el punto es literal. A veces se lee mejor. |
La opción -F | grep -F '192.168.1.1' | Cuando todo el patrón es texto literal. |
La barra invertida es, entonces, el interruptor del lenguaje. Delante de un metacarácter, lo apaga. Delante de ciertas letras, enciende un significado: \b es un borde de palabra, \w un carácter de palabra, \s un espacio en blanco.
11. Retrorreferencias
Los paréntesis tienen un tercer efecto: el texto con el que coincide cada grupo queda recordado, y se lo puede volver a exigir más adelante en la misma expresión.
Una retrorreferencia, \1, \2…, coincide con el mismo texto que coincidió con el primer grupo entre paréntesis, con el segundo, y así.
No significa «otra vez la misma forma», sino «otra vez lo mismo». ([a-z])\1 no es «dos letras», sino «una letra, y enseguida esa misma letra»:
$ grep -oE '[a-z]*([a-z])\1[a-z]*' <<< 'carro perro casa llave mesa'
carro
perro
llave
Sirve para encontrar repeticiones: una palabra escrita dos veces seguidas por error, una línea cuyo primer campo y cuyo último campo son iguales. En las búsquedas se usa poco. Su lugar natural es el reemplazo, donde permite reordenar o conservar partes de lo encontrado: «pon el segundo grupo antes del primero». Es una de las herramientas centrales de sed, en el tema 29.
12. Construir una expresión paso a paso
Una expresión regular larga no se escribe de corrido. Se construye como una tubería: una pieza por vez, comprobando en cada paso con grep -oE qué está coincidiendo. El método tiene cuatro pasos.
- Mirar ejemplos reales de lo que se quiere encontrar, y de lo que no. observar
- Describir la forma en palabras, de izquierda a derecha. describir
- Traducir cada parte a su pieza, agregándolas de a una y probando. traducir
- Anclar y ajustar: ¿coincide con algo que no debía? ¿se pierde algo que debía encontrar? verificar
Lo aplicamos a una pregunta: ¿en qué líneas el vendedor, es decir, el segundo campo, es Ana? El primer intento es el ingenuo:
$ grep -c 'Ana' ventas.csv # intento 1: «Ana», donde sea
3
$ grep -c ',Ana,' ventas.csv # intento 2: «Ana» como campo entero
3
$ grep -cE '^[^,]*,Ana,' ventas.csv # intento 3: «Ana» como SEGUNDO campo
3
Los tres dan el mismo número, y sin embargo solo el tercero es correcto. El primero fallaría el día que hubiera una vendedora «Anabel», o una ciudad «Santa Ana». El segundo fallaría con un producto llamado «Ana». El tercero dice exactamente lo pedido: desde el comienzo de la línea, un campo, una coma, y «Ana» seguido de coma.
Una expresión imprecisa da el resultado correcto mientras los datos no contengan el caso que la rompe. Por eso, además de mirar lo que encuentra, hay que pensar en lo que podría encontrar: probarla contra ejemplos inventados que no deberían coincidir es parte del trabajo.
La descripción en palabras, del segundo paso, es lo que vuelve legible cualquier expresión, propia o ajena. Esta, por ejemplo, selecciona de /etc/passwd las cuentas cuyo UID tiene cuatro cifras:
$ grep -E '^[^:]+:x:[0-9]{4}:' /etc/passwd
ana:x:1000:1000:Ana García,,,:/home/ana:/bin/bash
^ desde el comienzo de la línea
[^:]+ uno o más caracteres que no sean dos puntos: el nombre
:x: el texto «:x:»
[0-9]{4} exactamente cuatro dígitos: el UID
: dos puntos, para que no haya un quinto dígito
13. No son comodines
En el tema 9 dejamos anotado que los comodines de la shell y las expresiones regulares comparten símbolos con significados distintos. Ahora se puede completar la tabla:
| Símbolo | En un comodín de la shell | En una expresión regular |
|---|---|---|
* | Cualquier cantidad de caracteres cualesquiera. | Cero o más repeticiones del elemento anterior. |
? | Un carácter cualquiera. | El elemento anterior es opcional. |
. | Un punto. | Un carácter cualquiera. |
[abc] | Uno de esos caracteres. | Lo mismo. |
| Negación en corchetes | [!abc] | [^abc] |
^ y $ | Caracteres comunes. | Comienzo y fin de línea. |
| Quiero decir | Comodín | Expresión regular |
|---|---|---|
| Cualquier cosa | * | .* |
| Un carácter cualquiera | ? | . |
Termina en .txt | *.txt | \.txt$ |
Empieza con foto | foto* | ^foto |
Las dos últimas filas muestran una diferencia más de fondo. Un comodín debe describir el nombre entero; una expresión regular coincide con una parte, salvo que se la ancle. Por eso foto*, como expresión regular, significa otra cosa: «fot», seguido de cero o más letras o.
Y hay una diferencia de quién los interpreta, que decide cuál corresponde en cada lugar de una línea:
| Comodines | Expresiones regulares | |
|---|---|---|
| Los interpreta | La shell, antes de ejecutar | El programa que los recibe |
| Se comparan con | Nombres de archivos | Líneas de texto |
| Se escriben | Sin comillas | Entre comillas simples |
| Ejemplo | ls *.csv | grep '\.csv$' |
En grep -E '^Luis' *.csv conviven los dos: el patrón, entre comillas, es una expresión regular para grep; el último argumento, sin comillas, es un comodín para la shell.
14. Recetas y límites
Algunas expresiones de uso frecuente, para leer más que para copiar. Cada una se puede probar con grep -oE:
| Describe | Expresión |
|---|---|
| Una línea vacía | ^$ |
| Una línea vacía o solo con espacios | ^[[:space:]]*$ |
| Una línea de comentario | ^[[:space:]]*# |
| Un número entero | [0-9]+ |
| Un número con decimales opcionales | [0-9]+(\.[0-9]+)? |
| Una fecha año-mes-día | [0-9]{4}-[0-9]{2}-[0-9]{2} |
| Una hora | [0-9]{2}:[0-9]{2}(:[0-9]{2})? |
| Una dirección IP, de manera aproximada | ([0-9]{1,3}\.){3}[0-9]{1,3} |
| Una dirección de correo, de manera aproximada | [[:alnum:]._-]+@[[:alnum:].-]+\.[a-z]{2,} |
| El primer campo de un CSV | ^[^,]* |
| El último campo de un CSV | [^,]*$ |
Las palabras «de manera aproximada» no están de adorno. La expresión de la IP acepta 999.999.999.999, que no es una dirección válida. Describe la forma —cuatro grupos de dígitos separados por puntos—, no el significado. Esa es la frontera del lenguaje:
| Las expresiones regulares… | Consecuencia |
|---|---|
| Describen formas, no valores. | No saben que 31 es un día válido y 32 no, ni comparan números. |
| No entienden estructuras anidadas. | No sirven para analizar HTML, JSON ni código: para eso hay herramientas propias. |
| Crecen rápido en complejidad. | Una expresión de dos renglones que nadie puede leer es un error futuro. Suele ser mejor dividir el trabajo en dos pasos simples. |
Existe un tercer dialecto, más rico, que es el de la mayoría de los lenguajes de programación: las expresiones regulares de Perl, o PCRE. grep las acepta con la opción -P. Agregan atajos como \d para un dígito, y cuantificadores no codiciosos, como .*?, que toman lo mínimo. Lo aprendido en este tema vale también allí.
La referencia del tema, en sintaxis extendida:
| Símbolo | Significa |
|---|---|
. | Un carácter cualquiera. |
[abc], [a-z] | Un carácter del conjunto o del rango. |
[^abc] | Un carácter que no esté en el conjunto. |
[[:digit:]], [[:alpha:]], [[:space:]] | Un dígito; una letra; un espacio en blanco. |
^, $ | Comienzo y fin de la línea. |
\b | Borde de palabra. |
*, +, ? | Lo anterior, cero o más veces; una o más; cero o una. |
{n}, {n,}, {n,m} | Lo anterior, n veces; n o más; entre n y m. |
a|b | Una alternativa u otra. |
( ) | Agrupa, y recuerda lo que coincidió. |
\1 | El texto del primer grupo. |
\. | Un punto literal; la barra invertida quita el significado especial. |
Con grep las expresiones regulares sirven para encontrar. En el tema 29 las usamos para cambiar: sed busca con el mismo lenguaje, y reemplaza lo que encuentra.
15. Resumen
- Una expresión regular describe una forma de texto. La usan
grep,sed,awk, los editores y casi todos los lenguajes. - Se escribe entre comillas simples, y por defecto coincide en cualquier parte de la línea.
- El punto es un carácter cualquiera. Los corchetes, uno de un conjunto; con
^al comienzo, uno que no esté en el conjunto. ^y$anclan al comienzo y al final de la línea;\b, al borde de una palabra. Las anclas dan precisión.- Los cuantificadores se aplican al elemento anterior:
*cero o más,+uno o más,?opcional,{n,m}un rango. - Los cuantificadores son codiciosos:
.*abarca todo lo que puede. Una clase negada, como[^,]*, es más precisa. - La barra vertical separa alternativas, y los paréntesis agrupan: limitan una alternativa o permiten cuantificar varios caracteres.
- En la sintaxis básica,
+ ? { } ( ) |requieren una barra invertida para ser especiales; en la extendida, activada con-E, lo son directamente. - Una barra invertida delante de un metacarácter lo vuelve literal:
\.es un punto. \1coincide con el mismo texto que coincidió con el primer grupo.- Una expresión se construye de a una pieza, probando con
grep -oE, y pensando también en lo que no debe coincidir. - No son comodines: en una expresión regular el asterisco repite lo anterior y el punto es cualquier carácter.
16. Preguntas de repaso
Intenta responder cada una antes de abrir la respuesta.
1. ¿Qué describe una expresión regular?
Una forma: un conjunto de textos que tienen cierta estructura, en lugar de un texto fijo.
2. ¿Con qué coincide c.sa?
Con una c, un carácter cualquiera, una s y una a: «casa», «cosa», «c3sa», «c sa».
3. ¿Qué diferencia hay entre [abc] y [^abc]?
La primera coincide con un carácter que sea a, b o c. La segunda, con un carácter que no sea ninguno de los tres.
4. ¿Qué significan ^ y $? ¿Y ^$?
El comienzo y el final de la línea. ^$ describe una línea vacía: un comienzo seguido inmediatamente de un final.
5. En ^[^#] el circunflejo aparece dos veces. ¿Qué significa cada uno?
El primero, fuera de los corchetes, es el ancla de comienzo de línea. El segundo, dentro, niega la clase. La expresión describe una línea que empieza con un carácter distinto de #.
6. ¿Qué diferencia hay entre *, + y ??
Los tres se aplican al elemento anterior: * lo admite cero o más veces, + una o más, y ? cero o una.
7. ¿Con qué coincide [0-9]{2,4}?
Con una secuencia de entre dos y cuatro dígitos.
8. ¿Qué significa que los cuantificadores sean codiciosos?
Que toman la mayor cantidad de texto posible que permita coincidir al resto de la expresión. .*, llega hasta la última coma de la línea, no hasta la primera.
9. ¿Por qué [^,]* es preferible a .* para describir un campo de un CSV?
Porque no puede atravesar una coma: se detiene al terminar el campo. .* acepta también las comas y abarca varios campos.
10. ¿Qué diferencia hay entre (ab)+ y ab+?
En la primera, el + se aplica al grupo: «ab», «abab», «ababab». En la segunda, solo a la b: «ab», «abb», «abbb».
11. grep 'error|aviso' archivo no encuentra nada, aunque las dos palabras están. ¿Por qué?
Porque sin -E, grep usa la sintaxis básica, donde la barra vertical es un carácter literal. Hay que escribir grep -E 'error|aviso'.
12. ¿Cómo se busca un punto literal?
Con \., con [.], o usando grep -F si todo el patrón es texto literal.
13. ¿Qué describe ^[^:]+:[^:]*:0: aplicado a /etc/passwd?
Las líneas cuyo tercer campo es 0: desde el comienzo, un primer campo no vacío, dos puntos, un segundo campo, dos puntos, y un cero seguido de dos puntos. Es la cuenta con UID 0, root.
14. ¿Qué hace \1?
Coincide con el mismo texto que coincidió con el primer grupo entre paréntesis. (.)\1 describe un carácter repetido dos veces seguidas.
15. ¿Qué significa *.txt como comodín, y cómo se escribe lo mismo como expresión regular?
Como comodín, un nombre que termina en .txt. Como expresión regular se escribe \.txt$: un punto literal, «txt», y el fin de la línea.
Para practicar
- Con
grep -oEy la cadena'gato gata gatos gatitos perro', pruebagat.,gat[ao],gat[ao]s?,gat[a-z]+y\bgat[ao]\b. Predice cada resultado antes de ejecutarlo. - En
ventas.csv, encuentra con una sola expresión cada cosa: las ventas del día 5; las de importe de dos cifras; las de teclado o monitor; las que no son de Rosario. - Escribe una expresión que seleccione las líneas cuyo tercer campo es
Salta, usando un grupo con cuantificador. Compruébala. - Extrae con
grep -oEtodas las fechas distintas deventas.csv, y todos los nombres de producto distintos. - En
/etc/passwd: cuenta las cuentas con UID de un solo dígito; lista las que tienen un directorio personal dentro de/home; encuentra las que no terminan ennologinni enfalse. - En
informe.txt: cuenta las líneas vacías, las de comentario, y las que definen un servicio sobre un puerto de exactamente dos cifras ([[:space:]][0-9]{2}/). - Compara
grep -c 'a+' tareas.txtcongrep -cE 'a+' tareas.txty congrep -c 'a\+' tareas.txt. Explica los tres números. - Prueba la codicia con
grep -oE '".*"' <<< 'dijo "hola" y luego "chau"'. Corrige la expresión para obtener las dos citas por separado. - Con
ls -l /etc | grep -E, lista solo los directorios, luego solo los enlaces simbólicos, y luego los archivos que otros usuarios no pueden leer. - Describe en palabras, pieza por pieza, la expresión del correo electrónico de la sección 14. Inventa una dirección que no debería ser válida y que, sin embargo, coincida.