Existen una gran variedad de programas que reciben una entrada, la procesan y emiten una salida, a este tipo de programas le llamamos filtros. Estos son una parte fundamental del sistema ya que relacionando filtros simples se puede conseguir prácticamente cualquier cosa, a nivel de administración de archivos y scripts..
Entre estos filtros están:
cat | para mostrar la entrada. |
grep, tail, head y cut | para seleccionar una parte de la entrada. |
less y more | para paginar la entrada. |
sort | para ordenar la entrada |
tr | para alterar la entrada en forma ordenada. |
comm y diff | para comparar dos entradas. |
wc | para contar la entrada. |
Un comando muy útil que nos proporciona UNIX es grep
. Su función
principal es imprimir por pantalla solamente las líneas que concuerden con un
patrón que nosotros le indicamos.
Por ejemplo: ls -l | grep archivo
, nos mostrará todas
las líneas del ls -l
que concuerden con archivo
.
Algunas opciones de grep son:
-i
(ignore case) que no tiene en cuenta mayúsculas y minúsculas.
-n
para que muestre el número de línea dentro del archivo.
-v
para que muestre las líneas que no concuerdan con la
palabra ingresada.
Vamos a hacer un ejemplo de una agenda sencilla, utilizando el comando grep y unos scripts de shell. En primer lugar necesitamos tener un archivo con unas cuantas líneas de la forma: "nombre: teléfono". Por lo menos cuatro o cinco líneas, como para probar este ejemplo.
Una vez que hemos creado el archivo, crearemos el script, que se llamará 110,
y deberá contener la siguiente línea: grep -i "$*" agenda
. Y para
buscar un teléfono dentro de nuestra agenda haremos: 110 nombre
.
El comando tail
nos permite ver la cola de un archivo, es decir sus
últimas líneas (últimas 10 por omisión). Esto, aunque a simple vista no
parezca útil, resulta de gran utilidad para ver archivos grandes como, por
ejemplo, logs (archivos donde se guardan mensajes de estado y/o de errores).
Para probar el comando vamos a utilizar los logs del sistema, que se suelen
guardar en /var/log, en particular
/var/log/messages es el archivo que contiene gran parte de los mensajes del
sistema. Podemos hacer tail /var/log/messages
y compararlo con la salida
de cat /var/log/messages
.
Además a tail
podemos indicarle cuántas líneas queremos que nos
muestre. Con la opción -20, por ejemplo, le diríamos que nos
muestre 20 líneas y así con cualquier número que le pasemos.
Tambien podemos decirle que nos muestre el contenido del archivo a partir de
una determinada línea, por ejemplo tail +5 archivo
nos mostrará
el contenido del archivo desde la línea 5 en adelante.
Otro comando similar a tail
es head
. Su comportamiento es muy
similar, pero en lugar de mostrar las últimas líneas de la entrada, muestra
las primeras.
Este comando nos permite obtener una salida ordenada, si hacemos
ls | sort
obtendremos la salida de ls con un orden alfabético.
Ahora probemos ls -i | sort
, sort
ordena la salida de ls
alfabéticamente, eso quiere decir que los números no van a estar ordenados
de menor a mayor sino en orden alfabético. Para ordenarlos numéricamente
existe la opción -n, ls -i | sort -n
producirá una salida ordenada
de menor a mayor. Si quisiéramos, en cambio, que lo ordene de mayor a
menor, debemos usar ls -i | sort -nr
, es decir -r ordena en orden
inverso.
También podemos ordenar por una determinada columna, para entender esto de
una manera más clara veamos la salida de ls -l
, estas líneas pueden
ser ordenadas por tamaño, por nombre, por fecha, etc. Para eso tenemos que
indicarle cuál columna tiene que ordenar y con qué criterio.
Notar que sort cuenta las columnas empezando de 0.
Por ejemplo:
ls -l | sort +4nr
ordena la salida de ls
por el
tamaño dejando los más chicos al final. En este caso, la n, que indica
ordenamiento numérico es opcional, ya que sort
decide
automáticamente el ordenamiento.
ls -l | sort +4n +8
ordena la salida de ls
primero
por tamaño y luego por el nombre del archivo. En este caso, es necesario
poner la n, que indica ordenamiento numérico.
También existe un opcion -u que nos permite eliminar las lineas iguales adyacentes de la salida de sort. Es decir que si nuestra salida produce dos líneas iguales una debajo de otra, veríamos solamente una línea.
Este comando nos permite transliterar caracteres, es decir cambiar determinado
caracter por otro. Si escribimos tr 'a-z' 'A-Z' < archivo
,
veremos que tr transforma todas las minúsculas en mayúsculas.
Los parámetros del ejemplo anterior son rangos (de la 'a' a la 'z' y de la
'A' a la 'Z'), pero no es necesario que lo sean.
Lo que sí nos exige tr
es que los parámetros tengan
la misma cantidad de caracteres, o bien que el segundo sea un solo caracter.
En este último caso reemplazará
todos los caracteres del primer parámetro con el del segundo.
La opción -c
indica que deben transliterarse todos los caracteres
que no estén incluídos en el primer parámetro.
Ejemplo difícil:
cat archivo | tr -c 'a-zA-Z' '\n' | tr 'A-Z' 'a-z' | sort -u
El primer tr
convierte todo lo que no sea letras en \n
(retorno
de carro), el segundo convierte todas las mayúsculas en minúsculas y el
sort
del final las ordena alfabéticamente eliminando las líneas
iguales, con lo que obtenemos una palabra por línea.
Este comando nos sirve para comparar el contenido de dos archivos, línea por
línea. Para poder probar este comando, debemos crear dos archivos parecidos,
que tengan unas cuantas líneas en común, y otras distintas. Luego, debemos
hacer: comm archivo1 archivo2
.
La salida está separada en tres columnas: en la primera columna estarán las líneas que están en el primer archivo y no en el segundo, en la segunda columna veremos las líneas del segundo archivo que no estén en el primero y por último, en la tercera columna, las que están en los dos.
Además podemos indicar cuál de esas columnas no queremos que muestre, por
ejemplo comm -12 arch1 arch2
muestra solamente la tercera columna,
es decir, las líneas que están en ambos archivos.
El problema que tiene comm
es que espera que las líneas estén
ordenadas alfabéticamente, o en la misma posición dentro del archivo. De
modo que puede suceder que archivos muy similares sean procesados por
comm
como archivos muy diferentes. Para procesamiento más avanzado
de diferencias de archivos puede utilizarse el comando diff
.
Ejemplo:
En /usr/share/dict/ normalmente tenemos un archivo diccionario, en el cual encontramos una palabra por renglón. En especial, el archivo words suele ser un symlink al diccinario del idioma de nuestro sistema.
Lo que vamos a hacer es armar un pequeño analizador ortográfico,
usando los filtros recién vistos.
Utilizaremos comm
para verificar si la palabra está en el
diccionario, y que nos avise si no está.
Primero deberemos llevar el texto a una palabra por línea ordenada
alfabéticamente (que es el ejemplo que utilizamos con tr
).
Y luego, utilizar comm
para comparar con el diccionario.
El comando completo será:
cat archivo | tr -c 'a-zA-Z' '\n' | tr 'A-Z' 'a-z' | sort -u | comm -23 - /usr/share/dict/words
Notar que el - como parámetro del comm
le indica que use la entrada
estándar para leer el primer archivo.