Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Ordenar lneas de los archivos de entrada a partir de criterios de ordenacin. Los espacios en blanco son
tomados por defecto como separadores de campo.
Su sintaxis es de la forma:
sort [opciones] [archivo]
Ejemplos de uso, para lo cual se tomara como ejemplo el archivo pepe.txt cuyo contenido es:
# cat pepe.txt
15 windows
16 acer
2 actualizacion
1 actualizada
3 admiral
2 www
1 agregar
10 aires
1 al
1 algunos
1 empleos
60 en
2 equipo
45 archivos
3 word
sort pepe.txtOrdena el archivo pepe.txt
# sort pepe.txt
10 aires
15 windows
16 acer
1 actualizada
1 agregar
1 al
1 algunos
1 empleos
2 actualizacion
2 equipo
2 www
3 admiral
3 word
45 archivos
60 en
sort -k 1 pepe.txtOrdena el archivo usando el primer campo como clave de ordenacin. Tiene el mismos
efecto que sort pepe.txt
# sort -k 1 pepe.txt
10 aires
15 windows
16 acer
1 actualizada
1 agregar
1 al
1 algunos
1 empleos
2 actualizacion
2 equipo
2 www
3 admiral
3 word
45 archivos
60 en
sort -k 2 pepe.txtOrdena el archivo usando el segundo campo como clave de ordenacin.
# sort -k 2 pepe.txt
16 acer
2 actualizacion
1 actualizada
3 admiral
1 agregar
10 aires
1 al
1 algunos
45 archivos
1 empleos
60 en
2 equipo
15 windows
3 word
2 www
sort -n pepe.txtOrdena el archivo por valor numrico.
# sort -n pepe.txt
1 actualizada
1 agregar
1 al
1 algunos
1 empleos
2 actualizacion
2 equipo
2 www
3 admiral
3 word
10 aires
15 windows
16 acer
45 archivos
60 en
sort -nr pepe.txtOrdena el archivo por valor numrico de mayor a menor (invierte el orden).
# sort -nr pepe.txt
60 en
45 archivos
16 acer
15 windows
10 aires
3 word
3 admiral
2 www
2 equipo
2 actualizacion
1 empleos
1 algunos
1 al
1 agregar
1 actualizada
sort -t @ -k 2,2 pp.txt ordena el archivo pp.txt por el segundo campo, y el separador de campo que utilizo es
el @ arroba.
Un ejemplo de uso prctico es si tengo una lista desordenada (de por ejemplo una palabra por fila) y quiero
averiguar cuantas veces se repite cada palabra, para lo cual puede usar el comando:
sort -bdf lista | uniq -ic | sort -nr
Donde sort -bdf lista ordenar la lista, para que el comando uniq -ic pueda contar el nmero de lneas iguales
(considera iguales las maysculas y minsculas), por ltimo ejecuto sort -nr para que ordene la lista por la
palabra que se repite ms.
# cat ejemplo.txt
mama
pepe
hola
Hola
pepe
Hola
si
no
Mama
www
# sort -bdf ejemplo.txt | uniq -ic | sort -nr
3 hola
2 pepe
2 mama
1 www
1 si
1 no
Este comando es utilizado en conjunto con el comando uniq, ya que para encontrar lineas duplicadas
consecutivas primero hay que ordenar el contenido del archivo.
esta utilidad permite procesar secuencialmente uno o varios archivos, los cuales
constituyen la informacin entrante para awk. El contenido de cada una de las lneas de la
entrada se compara con una o varias plantillas, en las que debe especificarse un patrn de
bsqueda. A cada patrn se le asocia una accin, que, normalmente, procesa la
informacin entrante y la enva a la salida estndar.
Por tanto, los usos tpicos de awk se centran en la seleccin de registros de un archivo en
funcin de uno o varios criterios de bsqueda. Si solamente resultara relevante una parte
del registro seleccionado, tambin sera posible separarla e ignorar el resto.
La informacin "saliente" se puede transformar segn las necesidades del usuario, por lo
que es posible crear informes con muy poco esfuerzo de programacin.
La sintaxis es muy semejante a la del lenguaje C, con la particularidad de que, al
ser awk un intrprete, no es necesario pasar por procesos de compilacin y linkedicin. El
rendimiento de awk no es comparable al de un ejecutable, pero, dada la orientacin al
proceso secuencial de archivos, esta circunstancia solamente es relevante en condiciones
extremas.
Awk puede, adems, leer y grabar simultneamente otros archivos, adems de la entrada y
salida estndar. Otras capacidades avanzadas quedan, por su mayor dificultad, fuera del
alcance de este artculo.
Prerrequisitos
No se requiere el uso de una shell concreta. En los ejemplos se utiliza bash por ser capaz
de interpretar caracteres de control escritos con la sintaxis de escape con barra invertida.
$ awk
Usage: awk [-f programfile | 'program'] [-F fieldsep] [-v var=value] [files]
Awk sigue, como hemos indicado, un guin previamente escrito por el programador. Est
compuesto por plantillas, que indican --mediante una expresin-- qu registros se desea
procesar, y --mediante una accin-- qu proceso se pretende realizar con los registros
previamente seleccionados.
Ms adelante se mostrar cmo awk procesa cada registro como una sucesin de campos
separados por un carcter determinado que indica dnde termina un campo y empieza el
siguiente. La situacin ms habitual es aquella en la cual cada registro contiene una frase y
los campos son las palabras de la frase. El carcter delimitador es el espacio que separa
cada palabra de la siguiente. Mediante el parmetro F (ahora mayscula) se indica
a awk qu carcter debe considerar como separador de campos.
Tambin se mostrar la capacidad para usar variables dentro del guin, igual que en
otros lenguajes de programacin. Mediante el parmetro v se puede asignar un valor a
una variable desde la lnea de mandatos:
El resto de los parmetros son los nombres de los archivos de datos entrantes. El proceso
se realiza accediendo a los archivos en el orden especificado. Toma el conjunto de los
archivos como si fueran uno solo. Awk espera recibir por la entrada estndar (stdin) los
datos que debe procesar. Por ejemplo:
Suponga el lector que se desea actuar sobre un archivo de texto como el que se muestra a
continuacin. Contiene cuatro lneas de texto terminadas por el carcter de salto de lnea
\n, que no se muestra en la pantalla, salvo por el efecto de escribir en la lnea siguiente:
$ cat ejemplo.txt
La bella y graciosa moza
marchse a lavar la ropa
la frot sobre una piedra
y la colg de un abedul.
$ _
Todo el proceso gira en torno a la comparacin de todas las lneas del archivo, ledas una
por una en secuencia, con una o ms plantillas. Cada plantilla contiene una expresin, y
lleva asociada una accin. La sintaxis es, en general, de la forma:
expresin { accin }
En el siguiente ejemplo se pasa como nico parmetro la plantilla entre comillas simples:
Esta plantilla contiene una expresin trivial (1), cuya evaluacin resulta siempre positiva.
En ausencia de una accin asociada explcitamente, awk asume la accin por omisin, que
consiste en mostrar la lnea completa en stdout. Se puede aadir una accin algo ms
sofisticada entre llaves:
Como puede observarse, la accin print se realiza una vez por cada lnea que se obtiene de
stdin. Para emplear ms de una plantilla se emplea la construccin expresin { accin }
repetidas veces, como en el siguiente ejemplo:
Campos de entrada
Para utilizar una expresin que no sea trivial se debe introducir el concepto de campo. Se
considerar cada registro del archivo de entrada como una sucesin de campos delimitados
por un carcter dado. Este carcter es, por omisin, el espacio. Como se ha visto
anteriormente, se puede indicar a awk que considere otro carcter como separador de
campos mediante la opcin F (mayscula) en la lnea de mandatos.
Se hace referencia al contenido de cada campo usando el carcter $ (dlar) seguido del
ordinal del campo: $1, $2, $3, etc. Con la notacin $0 se hace referencia a la lnea entera.
Se puede forzar el proceso del registro carcter a carcter dejando la variable separador
de campos FS sin contenido. De este modo, en $1 se tendr el primer carcter de la lnea,
en $2 el segundo, etc. Incluso en este caso, el campo $0 contendr la lnea completa.
Como quiera que se est anticipando en estos ejemplos el uso de la instruccin "print", se
muestra a continuacin el guin anterior con las modificaciones necesarias para mostrar en
stdout el contenido de la primera y la segunda palabra de cada lnea:
$ cat ejemplo.txt | awk '1 { print Primera y segunda palabras ===>, $1, $2, "<=== final del
registro." }'
Variables
El programador puede crear sus propias variables smplemente haciendo referencia a ellas
en expresiones. Las variables pueden ser escalares (con un solo nombre y valor) o
vectoriales (con nombre, subndice y valor) El subndice puede ser una cadena arbitraria, lo
cual permite crear tablas asociativas. Se emplea la notacin nombre[ subndice ] para
referirse a un elemento de la tabla. Tambin se admite la definicin de variables de
naturaleza matricial, con nombre, varios subndices y varios valores, si se usa la notacin
nombre[ subndice1, subndice2, subndice3 ].
FS (Field separator): contiene el carcter que indica a awk en qu punto del registro acaba
un campo y empieza el siguiente. Por omisin es un espacio. Se puede indicar un carcter
alternativo mediante una instruccin de asignacin como FS = /. Si se deja vaco, cada
lectura se realiza dejando un carcter en cada campo.
NF (Number of fields): contiene el nmero total de campos que contiene el registro que se
est leyendo en cada momento.
RS (Record separator): contiene el carcter que indica a awk en qu punto del archivo
acaba un registro y empieza el siguiente. Es \n por omisin.
NR (Number of record): contiene el nmero de orden del registro que se est procesando
en cada momento.
Del mismo modo, se dispone de variables relativas a la informacin de salida, como las
siguientes:
OFS (Output FS): contiene el separador de campos para la salida generada por awk. La
instruccin print inserta en la salida un carcter de separacin cada vez que aparece una
coma en el cdigo. Por ejemplo:
manejo un apple
$ _
ORS (Output RS): Contiene el carcter que awk escribir al final de cada registro. Es \n
por omisin. Obsrvese que en esta modificacin del ejemplo anterior la entrada contiene
DOS registros, dada la aparicin del salto de lnea en el centro de la cadena de caracteres
entre comillas. Al modificar el carcter separador de la salida se genera un solo registro:
$ echo e "manejo un apple\ncaro y elegante" | awk v OFS = "\t" v ORS = \t 1 {print $1, $2, $3}'
Operadores
Son aplicables los operadores comunes en C para realizar operaciones aritmticas sobre
variables con valores numricos, y para concatenar los valores contenidos en variables con
valores alfanumricos. As, se tiene:
+ Suma
- Resta
* Multiplicacin
/ Divisin
% Resto
^ Exponenciacin
Esp Concatenacin
! Negacin
A *= N Multiplicar por N
A /= N Dividir por N
== Igual a
!= Distinto de
Awk en accin
Para recapitular lo visto hasta ahora, se realizar a continuacin algn proceso sencillo con
el archivo de ejemplo mostrado en prrafos anteriores. El archivo entrante contiene un
nmero tericamente no determinado de registros, terminados por el carcter contenido en
RS. El proceso comienza leyendo el primer registro, aplicando a ste todas las plantillas
existentes con el valor de la variable NR igual a 1. Se reitera el proceso para cada registro,
incrementando en una unidad el valor de NR cada vez.
Cada registro est compuesto por NF campos, delimitados por las apariciones del carcter
FS en el mismo. El ordinal de cada campo se designa, como se indic arriba, con $1, $2,
$3 y as hasta $NF.
Con campos, variables y operadores se puede escribir una plantilla algo ms til que las
anteriores:
$ awk '$5 == moza { print La linea, NR, "contiene MOZA en el quinto campo; }' ejemplo.txt
$ cat proceso.awk
La primera plantilla siempre se ejecuta por no tener expresin delante de las llaves. La
segunda solamente se activa para las lneas que tienen ms de una palabra. La tercera es
aplicable si la lnea comienza con la palabra Linux.
Dos expresiones especiales, BEGIN y END, permiten realizar acciones antes de procesar el
primer registro, y despus de procesar el ltimo, respectivamente.
El sencillo script suma.awk pone a cero la variable total antes de iniciar el proceso del
archivo de entrada, aade a esa variable el valor correspondiente al contenido del primer
campo de cada registro, y muestra el valor de la variable al final:
$ cat suma.awk
BEGIN { total = 0 }
{ total += $1 }
END { print El total es, total }
Para ejecutarlo, se puede usar lo siguiente (obsrvese que la entrada tiene cuatro
registros):
El total es 100
Instrucciones de control
{
print Procesando registro, NR;
if( $1 > 0 )
{ print "positivo";
print "El primer campo tiene:", $1;
}
else
{
print "negativo";
}
}
donde la primera expresin suele poner valor inicial al ndice. En la segunda se controla
hasta qu momento la ejecucin debe continuar. La tercera marca el nivel de incremento
de la variable ndice.
{
for( i = 0; i < 10; i ++ )
{
j = 2 * i;
print i, j;
}
}
En su segunda forma, la construccin for recorre los elementos de una matriz (array).
Dado el carcter avanzado de este concepto, quedar para un segundo artculo su manejo.
Funciones
Las funciones predefinidas del lenguaje responden al concepto habitual en otros lenguajes
de programacin. La llamada a una funcin se resuelve en tiempo de ejecucin. Cuando se
evala una expresin, se realiza la sustitucin de la llamada a la funcin por el valor que
sta devuelve. Por ejemplo:
$ awk 'BEGIN { print El seno de 30 grados es, sin( 3.141592653589 / 6 ); }' /dev/null
Se dispone de las funciones matemticas y trigonomtricas exp, log, sqrt, sin, cos y atan2.
Adems, son de mucha utilidad las siguientes:
La solucin definitiva
El lector avezado debera estar, a estas alturas, preparado para afrontar el desafo del
principio del artculo. Con los mimbres mostrados en las pginas anteriores se tratar de
hacer el cesto deseado. Ser suficiente con que el guin awk resultante sea capaz de
construir un shell script que contenga los mandatos necesarios para autorizar el acceso de
los alumnos al servidor web.
$ cat alumnos.txt
Sebastin Palomo Linares spl18901 jalisco
Pedro Prez Pino ppp0 hatalue
John Jensen jotajota whatafew
Mara del Carmen Garca Feo mc98819 uglymom
$ _
En la salida se desea generar un shell script con el comentario que indica el nombre de la
shell a emplear (#!/bin/bash, por ejemplo) en la primera lnea, y con una lnea
como /usr/bin/htpasswd b usuario contrasea" por cada alumno.
Para poner una pizca de dificultad al problema, pondremos de manifiesto un hecho que
seguramente no extraar al lector; los nombres no tienen un nmero fijo de palabras, y
no se garantiza que todos los alumnos estn expresados con los dos apellidos. As que el
planteamiento simplista que hara un anglosajn no muy despierto, consistente en asociar
$1 con el nombre, $2 con el apellido, $3 con la cuenta y $4 con la contrasea, no conduce
al resultado correcto:
Otra dificultad que puede presentarse viene dada por la eventual inexistencia de la base de
datos de autorizaciones del servidor web en el momento de la ejecucin del script. A los
efectos de la programacin, implica aadir la opcin -c a la primera llamada al
mandato htpasswd dentro del script que se genera.
5
5
4
7
Pero, lo que es realmente maravilloso en este caso es que podemos acceder al valor del
campo que se encuentra en el ltimo lugar con tan solo $NF en lugar de NF:
5 : jalisco
5 : hatalue
4 : whatafew
7 : uglymom
spl18901
ppp0
jotajota
mc98819
spl18901 jalisco
ppp0 hatalue
jotajota whatafew
mc98819 uglymom$ _
Para dar los toques finales con ms comodidad se escribira el guin en un archivo llamado
altaweb.awk :
$ cat altaweb.awk
La ejecucin del proceso se realiza, como antes, con el mandato que se muestra a
continuacin:
Solamente resta verificar el contenido del shell script y ejecutarlo. Cuando se tenga
confianza en el resultado se puede obviar el paso intermedio y ejecutar directamente:
Conclusin
Awk es un poderoso intrprete, que permite realizar tareas con archivos de tipo secuencial
con una elevada efectividad. La eficacia de su uso en procesos automatizados es innegable,
a la vista de que mi jovial colaborador ha desistido, y se dispone a reinstalar Windows. Sin
embargo, disfrutar de lo lindo con su salvapantallas de tiburones simultaneado con
apariciones espordicas de una misteriosa pantalla azul en la que se glosan las maravillas
de la Excepcin 0E Hasta ms ver.
luis:x:504:504:Luis Hernandez:/home/luis:/bin/bash
Bien, supongamos que deseamos un listado de todos los usuarios normales (personas) del
sistema, pero solo necesitamos su nombre de usuario, su nombre o real y su shell por defecto,
es decir, si vemos la lnea anterior, la separacin entre campos es ":" asi que para nuestro
reporte queremos el campo 1,5 y 7. Pero adems, este reporte ser parte de una tabla HTML,
asi que sera bueno si puderian incluirse de una vez las etquietas "<tr> y "<td> necesarias de
una vez. Es decir, el resultado deseado es el siguiente:
<tr><td>luis<td><td>Luis Hernandez</td><td>/bin/bash</td></tr>
El primer paso es determinar los usuarios normales del sistema, podramos usar un grep
"home" /etc/passw | gawk ..., pero podra haber usuarios que tengan su HOME en otra
ubicacin, adems se trata de usar solo awk, asi que lo primero que entenderemos es que los
campos obtenidos del resultado de un comando awk, se numeran por $1, $2, etc. y el
delimitador de campos se indica mediante la variable "FS".
Aunque no muy til todava, podemos ver como seleccionamos el caracter separador FS=":",
que viene de 'Field Separator', y tenemos indicada una accin '{print $3}', que significa
imprime el campo 3. Aunque realmente no lo queremos imprimir, lo queremos evaluar, y si
deseamos imprimir el $1, $5 y $7 que se mencionarion previamente, asi que agregamos una
expresin de evaluacin antes de la accin:
#> awk '$3 >= 500 {print $1 $5 $7 }' FS=":" /etc/passwd
sergonSergio Gonzalez/bin/bash
valeriaValeria Perez/bin/bash
fernandaFernanda Lozano/bin/sh
alejandraAlejandra Lopez/bin/nologin
luisLuis Hernandez/bin/bash
Mucho mejor, agregamos '$3 >= 500' previo a la accin (que es imprimir lo que deseamos), ya
que como se sabe en la mayora de distros modernas, los usuarios normales del sistema se
numeran del 500 en adelante (ms sobre administracin de usuarios). Ntese que los campos
en el resultado salen pegados, es necesario agregar entre comillas " ", ya sea un espacio o lo
que se desee, en este caso etiquetas de tablas de HTML y adems ordenaremos "sort" los
registros obtenidos: