Capitulo 2 - Shell Script
Capitulo 2 - Shell Script
Shell Scripts
2. Shell Scripts
La administracin de red es una ardua, pero hermosa tarea; como administrador se debe conocer y tener a la mano un conjunto de herramientas o utileras para prevenir, evitar y corregir problemas en la red. El administrador debe conocer, controlar y planificar los procesos del sistema, conocer los archivos donde se almacenan informacin de los usuarios, compartir archivos, controlar recursos, conocer e instalar herramientas de monitoreo, conocer e instalar herramientas para realizar encriptacin, controlar el acceso al sistema, y muchas otras actividades extras; como se puede notar la labor de un administrador es una tarea titnica, y es mejor y ms recomendado que estas tareas recaigan en un grupo de personas y no en una sola. Para empezar este captulo, hablaremos primero del shell del sistema, en que consiste y algunos comandos que consideramos importantes, en la siguiente seccin, tocaremos el punto de su programacin, y en la ltima seccin hablaremos de la programacin con el lenguaje AWK.
2.1.1 El ambiente del sistema UNIX Antes de empezar a hablar de la programacin del shell, veamos en que consiste el sistema operativo UNIX. El sistema operativo UNIX consiste de un kernel, un shell y cientos de comandos o utileras. El kernel es la parte que interacta directamente con el hardware, este administra la memoria, controla los dispositivos de entrada y salida, y proporciona una serie de servicios a travs del shell. El shell interacta con el kernel de modo transparente para el usuario. As la combinacin del kernel, el shell, los comandos y el hardware es lo que forma al sistema UNIX. UNIX proporciona un ambiente de trabajo que consiste de dos grandes subsistemas: El sistema de archivos, el cual es una definicin fsica, conceptual y organizacional de los archivos en el sistema, y
UTM IEC.
El sistema de control de procesos, el cual se debe conocer para poder interactuar con el resto del ambiente, su tarea principal es relacionar un programa (especialmente el shell) y otros programas en ejecucin.
2.1.2 El shell de UNIX y el usuario El shell es uno de los programas que se distribuyen con el sistema UNIX, este se encarga de interpretar las rdenes que colocamos desde el teclado o desde un script. Cuando nos conectamos a una computadora con UNIX, el proceso login invoca al programa de shell llmese Bourne shell, korn shell, C shell, etc, esto depende del sistema y del administrador, en la tabal 2-1 se muestran los shells tpicos de UNIX. El shell de cada usuario esta determinado en una de las entradas del archivo /etc/passwd, en la figura 2-1 se muestra parte de un archivo passwd y se coloca con negrita el shell de cada usuario. El shell se encarga de establecer y mantener el ambiente de trabajo, el cual esta definido en el archivo .profile. El .profile es un claro ejemplo de un script, en la figura 2-2 se muestra un archivo de este tipo.
Tabla 2-1. Los shells del sistema UNIX Descripcin Versin GNU del shell estndar con caractersticas aadidas del shell C. Este shell es el estndar de los sistemas LINUX. El shell C de Berkeley. El shell de trabajo, una extensin del shell estndar. El shell Korn. El tradicional shell de Bourne. Versin mejorada de csh. Versin mejorada de ksh. .
hsuarez:x:202:202:Hugo Suarez Onofre:/export/home/usuarios/hsuarez:/usr/bin/csh ic981476:x:1476:211:Cruz Perez Javier:/export/home/alumnos/ic981476:/bin/csh rglist:x:242:220:red-utm:/export/home/listas/rglist:/bin/csh pglist:x:248:220:red-utm:/export/home/listas/pglist:/bin/csh gcgero:x:373:201:Gabriel Geronimo Castillo:/export/home/usuarios/gcgero:/bin/ksh bibliote:x:405:10:Proyecto Biblioteca:/opt/bibliote:/bin/csh ohayna:x:1829:211:Otilia Hayna:/export/home/alumnos/ohayna:/bin/csh ercomar:x:1287:211:Proyecto de Energia:/export/home/alumnos/ercomar:/bin/csh id971355:x:1355:211:Montes Velasco Emma:/export/home/alumnos/id971355:/bin/csh id941402:x:1402:211:Maur Cruz James:/export/home/alumnos/id941402:/bin/csh ecg:x:396:207:Enrique Contreras Gonzalez:/export/home1/usuarios/ecg:/bin/sh
# archivo .profile # @(#)local.profile 1.4 93/09/15 SMI # #setenv DISPLAY 192.100.170.30:0.0 PS1="[email protected]>" stty istrip PATH=/usr/bin:/usr/ucb:/etc:. export PATH #setenv DISPLAY 192.100.170.30:0.0 # # If possible, start the windows system # if [ `tty` = "/dev/console" ] ; then if [ "$TERM" = "sun" -o "$TERM" = "AT386" ] ; then if [ ${OPENWINHOME:-""} = "" ] ; then OPENWINHOME=/usr/openwin export OPENWINHOME fi echo "" echo "Starting OpenWindows in 5 seconds (type Control-C to interrupt) sleep 5 echo "" $OPENWINHOME/bin/openwin clear # get rid of annoying cursor rectangle exit # logout after leaving windows system fi fi
Figura 2-2. Ejemplo de un archivo .profile El shell cuenta adems con un conjunto de variables de ambiente que se fijan automticamente al inicio de una sesin o las puede fijar el usuario, esto con la finalidad de facilitar y personalizar el ambiente de trabajo, el comando set se puede utilizar para visualizar las variables actuales del shell y sus valores. [email protected]>set ERRNO=9 FCEDIT=/bin/ed HOME=/export/home/usuarios/gcgero HZ=100 IFS=' ' LC_COLLATE=es LC_CTYPE=es LC_MESSAGES=es LC_MONETARY=es_MX LC_NUMERIC=es LC_TIME=es LINENO=1 LOGNAME=gcgero MAIL=/var/mail/gcgero
MAILCHECK=600 OPTIND=1 PATH=/usr/bin:/usr/ucb:/etc:. PPID=14034 PS1='[email protected]>' PS2='> ' PS3='#? ' PS4='+ ' PWD=/export/home/usuarios/gcgero RANDOM=23554 SECONDS=7 SHELL=/bin/ksh TERM=vt100 TMOUT=0 TZ=Mexico/General _=PATH Las variables de shell comunes se muestran en la tabla 2-2. Algunas veces se necesita obtener el valor de una variable del shell, para esto debemos de colocar antes del nombre de la variable el signo $, y para ver el valor de la variable utilizamos la orden echo. [email protected]>echo $HOME /export/home/usuarios/gcgero Las variables de ambiente las podemos utilizar para no tener que teclear un camino completo, por ejemplo si est ubicados en el directorio /etc y queremos regresar a nuestro directorio de trabajo podemos utilizar la variable HOME: [email protected]>pwd /etc [email protected]>cd $HOME [email protected]>pwd /export/home/usuarios/gcgero [email protected]> Tabla 2-2. Variable de ambientes habituales. Descripcin Ejemplo Nombre del camino de HOME= Fijado por el usuario. su directorio de trabajo /export/home/usuarios/gcgero Nombre de usuario LOGNAME=gcgero Fijado automticamente en el inicio de la sesin. Utilizado por el shell para notificar el correo. Frecuentemente checa cada 600 segundos (10 minutos) .
LOGNAME MAIL
Nombre del camino que MAIL=/var/mail/gcgero contiene su correo. MAILCHECK= Checa cambios en los MAILCHECK=600 600 parmetros de los archivos especificados por MAILPATH o MAIL. PATH Lista de directorios PATH=/usr/bin:/usr/ucb:/etc:. Fijada
automticamente
TZ IFS
PWD
donde el shell busca las rdenes. Indicador primario del shell Indicador secundario del shell Ruta de su shell. Define su tipo de terminal para vi, pine y otras rdenes orientadas a pantalla. Informacin de la zona de horario. Utilizado para separar comandos, opciones y argumentos; usualmente es un espacio, un tab, o una nueva lnea. Contiene el nombre del directorio de trabajo. Contiene el nombre del directorio anterior. Contiene un entero aleatorio.
al iniciar la sesin. PS1='[email protected]>' PS2='> ' SHELL=/bin/ksh TERM=vt100 Fijado automticamente o por el usuario. Por omisin de > Fijada automticamente Fijada por el usuario.
OLDPWD RANDOM
SECONDS
PWD=/export/home/usuarios/ El usuario lo puede fijar. gcgero Esta variable se encuentra en el shell korn. Esta variable se encuentra en el shell korn. RANDOM=23554 Toma una distribucin uniforme entre 0 y 32767.Esta variable se encuentra en el shell korn. SECONDS=7 Esta variable se encuentra en el shell korn.
Existen tambin unas variables especiales que son muy tiles en el momento de programar el shell, estas variables son: # ? Utilizada para comprobar si existen argumentos de lneas de rdenes, y si es as cuantos existen. Contiene el valor devuelto por la ltima orden ejecutada; cuando se ejecuta una orden, esta devuelve un nmero al shell, 0 en caso de una orden con xito, y un valor diferente de 0 en caso de que la orden falle. Contiene el ID (identificador) del ltimo proceso subordinado (en background).
Las variables de shell son utilizadas fundamentalmente por los programas, incluyendo el propio shell, sin embargo, puede definir tambin nuevas variables de shell para su propio uso. Por ejemplo, si mueve con frecuencia archivos a un directorio particular, puede definir una variable con el nombre del directorio. [email protected]> DEST = \home\ usuario1\redes\script
Ahora, ya puede mover archivos desde cualquier punto del sistema escribiendo [email protected]> mv file $DEST Si queremos referirnos a un simple archivo usualmente tenemos que colocar su nombre de entrada, pero si queremos referirnos a varios archivos en una sola lnea, el shell nos proporciona caminos ms cortos al poder utilizar caracteres especiales, llamados metacaracteres del shell. Estos metacaracteres dependen del tipo de shell de trabajo, en la tabla 2-3 se muestran algunos metacaracteres usados en la utilizacin y programacin del shell. Tabla 2-3. Metacaracteres Metacaracter Funcin Ejemplo < Redirecciona la entrada de un archivo a xxx < archivo xxx. > Redirecciona la salida de xxx a un archivo. xxx > file >> Aade la salida de xxx a un archivo. xxx >> archivo 2> Enva el error estndar que se produzca a xxx 2> archivo un archivo. 2>> Aade el error estndar a un archivo. xxx 2>> archivo | Ejecuta un archivo y enva la salida a otro archivo | archivo archivo. & Ejecuta un archivo en modo subordinado o archivo & background. ; Ejecuta un archivo y despus al siguiente archivo ; archivo que se encuentra delante de l. * Comodn de nombre de archivo, sustituye x*y a cualquier carcter en los nombres de archivo. ? Comodn de nombre de archivo, sustituye x?y un slo carcter. [...] Identifica a cualquier carcter del conjunto [Aa]rchivo encerrado entre []. = Utilizado para asignar un valor a una HOME= /export/usuarios/home/gcgero variable de shell. \ Elimina el significado del siguiente carcter especial y la unin de lnea. .... Se utiliza para que el shell no interprete el texto entre comillas simples. . 2.1.3 Entrada y salida del shell El shell asocia a cada programa que ejecuta tres archivos abiertos: entrada estndar (por lo general el teclado), salida estndar (por lo general la pantalla) y error estndar (por lo general la pantalla). Estos tres archivos se asignan normalmente a la terminal, pero se pueden redirigir con facilidad utilizando los metacaracteres mostrados en la tabla 2-3.
Entrada y salida estndar Archivo Teclado Orden Entrada estndar ORDEN Salida estndar Archivo Pantalla Orden
El shell proporciona dos rdenes internas para la escritura de la salida y para la lectura de la entrada: echo y read. La orden echo permite escribir salida desde la consola o desde un programa de shell, y puede trabajar con alguna o algunas de las siguientes secuencias de escape: \b Backspace. \c Imprime la lnea sin nueva lnea. \f Siguiente pgina. \n Nueva lnea. \r Return. \t Tabulador. \v Tabulador vertical. \\ Barra invertida. La orden read permite insertar la entrada del usuario en el script, read lee slo una lnea de entrada del usuario y la asigna a una o ms variables del shell. Cuando programa puede asignarle un nombre a la variable en la cual se almacenar el dato ledo o si no lo hace, se utiliza la variable REPLY por defecto. Cuando se utiliza read con varios nombres de variables, el primer campo tecleado por el usuario se asigna a la primera variable, el segundo campo a la segunda variable y as sucesivamente. Los campos que sobran a la izquierda son asignados a la ltima variable. Para que el shell reconozca donde empieza un campo, se auxilia de la variable de ambiente IFS (Internal Fiel Separator), la cual tiene el valor por defecto de un espacio en blanco; si desea utilizar un carcter diferente para separar campos simplemente se redefine la variable del shell IFS, por ejemplo IFS = : fijar el separador de campo al carcter dos puntos (:). Ejemplo 1: # Descompone la entrada del usuario en campos IFS=: echo Escriba algunas palabras utilice la barra espaciadora como separacin read palabra1 palabra2 palabra3 palabra4 palabra5 echo \n Campo 1: $palabra1 echo \n Campo 2: $palabra2 echo \n Campo 3: $palabra3 echo \n Campo 4: $palabra4
2.1.4 Desplazamiento de los parmetros posicionales Todos los argumentos de la lnea de rdenes estn asignados por el shell a parmetros posicionales; el valor del primer argumento de la lnea de rdenes est contenido en $1, el valor del segundo en $2, el tercero en $3 y as sucesivamente. Para reordenar los parmetros posicionales utilizamos el comando shift, el cual cambia $2 a $1, $3 a $2, $4 a $3 y as sucesivamente, y el valor original de $1 se pierde.
2.2.1 Ejecucin condicional Para proporcionar ms potencia de programacin, el shell incluye constructores para realizar decisiones en base a funciones de pruebas lgicas.
2.2.1.1 La orden if La orden if proporciona control simple al programa a travs de bifurcaciones simples, la forma general de la orden if es: if orden then ordenes fi Las ordenes siguintes a then se ejecutan si se cumple con xito la expresin orden de if. El fi marca el final de la estructura if. En el sistema UNIX las ordenes a evaluar retorna 0 (verdadero) para indicar que se evaluaron normalmente, en caso contrario devuelve un nmero diferente de 0 (falso). Ejemplo 2: #!/bin/ksh # Script enviar
# Envar un mensaje al usuario y eliminar el mensaje si el envo tiene xito if mail $LOGNAME < mensaje then rm r mensaje fi
2.2.1.2 La orden test Para utilizar las operaciones if-then en los programas de shell se necesita evaluar alguna expresin lgica y ejecutar alguna orden en base al resultado de esta evaluacin. La orden test permite realizar comparaciones explcitas. Test retorna un valor igual a 0 si la expresin evaluada es verdadera y un nmero diferente de 0 si la expresin es falsa. Test permite evaluar cadenas, enteros y el estado de archivos del sistema UNIX, note adems que test devuelve un estado diferente de 0 si no se le da una expresin. Comprobacin de enteros. n1 eq n2 n1 ne n2 n1 gt n2 n1 ge n2 n1 lt n2 n1 le n2 verdadero si n1 = n2 verdadero si n1 n2 verdadero si n1 > n2 verdadero si n1 >= n2 verdadero si n1 < n2 verdadero si n1 <= n2
Comprobacin de cadenas. -z cadena -n cadena cadena1 = cadena2 cadena1 != cadena2 cadena1 verdadero si la longitud de la cadena es 0. verdadero si la longitud de la cadena es diferente de 0, es decir, si existe cadena. verdadero si cadena1 y cadena2 son idnticas. verdadero si cadena1 y cadena2 no son idnticas. verdadero si cadena 1 no es la cadena nula.
Comprobacin de archivos. -a archivo -r archivo -w archivo -x archivo -f archivo -d archivo -h archivo -c archivo -b archivo -p archivo -s archivo verdadero si existe el archivo. verdadero si existe el archivo y puede leerse. verdadero si existe el archivo y puede escribirse. verdadero si existe el archivo y es ejecutable. verdadero si existe el archivo y es un archivo regular. verdadero si existe el archivo y es un directorio. verdadero si existe el archivo y es un enlace simblico. verdadero si existe el archivo y es un archivo de caracteres especiales. verdadero si existe el archivo y es un archivo especial de bloque. verdadero si existe el archivo y es un cauce con nombre. verdadero si existe el archivo y tiene un tamao mayor que cero.
-o Ejemplo 3:
#!/bin/ksh if test $# -eq 0 then echo Use: posic archivo exit 2 fi mail $1 < mensaje exit 0 Ejemplo 4: #!/bin/ksh if test n $1 then person= $1 fi
Ejemplo 5: #!/bin/ksh # Script catt # verifica primero si existe el archivo para ver su contenido # utilizando el programa cat if test r $1 then if test r $1 then cat $1 else echo el archivo - $1 -no existe en esta ruta: $PWD exit 1 fi else echo use : catt archivo exit 2 fi
Existe una forma alternativa de especificar el operador de comprobacin test por medio de [ ], as por ejemplo test $# -eq 0 test z $1 test tam=$1 es equivalente a es equivalente a es equivalente a [ $# -eq 0 ] [ -z $1 ] [tam = $1 ]
2.2.1.3 La orden if-then-else La operacin if-then-else permite bifurcacin en doble camino en funcin del resultado de la orden if if orden then ordenes else ordenes fi
2.2.1.4 La orden if-then-elif La orden if-the-elif permite crear un gran conjunto de comprobaciones if-then anidadas if orden then ordenes elif orden then ordenes else ordenes fi 2.2.1.5 La orden case Una forma alternativa de if-then-elif, es la orden case que proporciona una forma ms simple y legible para realizar las mismas comprobaciones. case cadena in Lista-de-patrones ) Ordenes ;; Lista-de-patrones ) Ordenes ;; ..... ..... ..... esac case opera de la siguiente forma: El valor de cadena se compara con cada uno de los patrones, si se encuentra una identificacin, las rdenes que siguen al patrn se ejecutan hasta el doble punto y coma (;;) donde finaliza la sentencia case. El carcter * (asterisco) identifica a cualquier valor de cadena y proporciona una forma de especificar una accin por defecto, el uso de * es un ejemplo de comodn de nombre de archivo de shell en patrones case. Ejemplo 6: #! /bin/ksh # script borrar
# Borra un archivo, slo si el usuario esta seguro de hacerlo # verifica que haya dado un argumento. if [ -n $1 ] then # verifica si el archivo es regular if [ -f $1 ] then echo Borramos el archivo ?\c read ok case $ok in # verifiquemos si la respuesta es: y o Y o yes o YES o OK o ok [Yy]* | OK | ok) echo Borrando archivo .. sleep 1 rm $1 exit 0 ;; #verifica si la respuesta es: No o no [Nn]*) echo El archivo no fue borrado . sleep 1 exit 1 ;; esac else # verifica si es un directorio if [ -d $1 ] then echo No puedo borrar $1 es un directorio exit 1 else echo no puedo borrar el archivo exit 2 fi fi else echo use: borrar archivo exit 3 if
2.2.2 Loops 2.2.2.1 La orden for El bucle for ejecuta una lista de rdenes una vez para cada miembro de una lista, el formato bsico es: for i [ in lista ] do Ordenes done
La variable i en la sintaxis anterior puede ser cualquier nombre que se elija, si se omite la porcin in lista de la orden, las ordenes entre do y done sern ejecutadas una vez por cada parmetro posicional que se coloque. Ejemplo 7: #!/bin/ksh # script lista # ejemplo que muestra como se utiliza una lista for i in 1 2 3 4 5 6 7 8 9 do echo Hola mundo done Ejemplo 8: #!/bin/ksh #script buscar # suponga que tiene un archivo (llamado agenda) en el cual coloco nombres, direcciones y telfonos de # sus amigos, y desea buscar si se encuentran ciertos nombres en el archivo # if [ -n $1 ] then for i do grep $i $PWD/agenda done else echo use: buscar agenda exit 1 fi al ejecutar colocamos: buscar hugo paco luis
2.2.2.2 Las ordenes while y until Las ordenes while y until proporcionan una forma simple para implementar el control de comprobacin-iteracin-comprobacin. while ordenes1 do ordenes2 done Esto es, si ordenes1 es verdadero entonces se ejecuta ordenes2, si no finaliza el while. Para until se sigue la sintaxis: until ordenes1
do ordenes2 done La nica diferencia entre las ordenes while y until se encuentra en la naturaleza de comprobacin lgica que se realiza en parte superior del bucle.
2.2.3 Las ordenes break y continue Normalmente, cuando se establece un bucle utilizando las ordenes for, while y until (y la orden select en ksh), la ejecucin de las rdenes englobadas en el bucle contina hasta que se cumple la condicin lgica del bucle. El shell proporciona dos formas para alternar el funcionamiento de las ordenes en un bucle, una de ellas es break, el cual permite salir del bucle inmediato que lo engloba, y continue el cual es opuesto a break, controla la vuelta al principio del bucle ms pequeo que lo engloba.
2.2.4 La orden select La orden select se utiliza para visualizar un nmero de elementos sobre la salida estndar y espera entrada, si el usuario pulsa return sin realizar una seleccin, la lista de elementos se visualiza de nuevo hasta que se da una respuesta. Select es muy utilizado en programas que permiten a los nuevos usuarios selecciones de un men en lugar de entradas por rdenes para operar un programa. La orden select slo se encuentra en el shell korn.
2.2.5 Las ordenes true y false Dependiendo de las comprobaciones y comparaciones los scripts retornan un valor verdadero (0) o falso (0), las ordenes true y false retornan dos valores especficos, true devuelve siempre 0 y false un nmero diferente de 0. El uso fundamental de estas ordenes es el establecimiento de bucles infinitos. while true do ordenes done
until false do ordenes done Note que dentro del bucle debe existir alguna accin que provoque un break para poder salir.
2.2.6 Operaciones aritmticas Para evaluar expresiones aritmticas los shells cuentan con las siguientes instrucciones: expr let (( )) en sh en ksh en ksh, la cual es una abreviacin de let.
Las instrucciones que trabajan mejor, sin ocasionar tantos problemas son let y (( )). Cabe hacer notar que let automticamente utiliza el valor de una variable, no debemos anteponerle el smbolo $. La orden let se puede utilizar para todas las operaciones aritmticas bsicas (+,-,*,/,%), tambin proporciona operaciones ms especializadas, como conversin entre bases y operaciones bit a bit and (&) y or (|). Ejemplo 9: #!/bin/ksh # script imprime # script coloca en pantalla del 1 al 10 i=1 while ((i<=10)) do echo $i ((i=i+1)) done 2.2.7 Depuracin de programas de shell Algunas veces nos damos cuenta que los script no funcionan de la manera que esperbamos, quizs escribimos mal una orden o no colocamos las comillas o caracteres especiales. Cuando cometemos un error en el mejor de los casos el script no se ejecutar, o en el peor de los casos un error en el nombre de una orden producir que la orden realice algo indebido, por ejemplo, rm *.tmp es diferente que rm * .tmp, el espacio entre * y .tmp har que todos los archivos del directorio actual se borren. Para inspeccionar la ejecucin de cada lnea del script, se utiliza la orden: sh x script Esta orden le indica al shell que imprima cada orden y sus argumentos conforme se van ejecutando.
2.3.1 El formato de una script awk Un script awk puede tener tres secciones: Una seccin de BEGIN, la cual inicializa el script. Esta seccin es ejecutada solamente al inicio del script, antes de que cualquier registro sea ledo del archivo o archivos de entrada. La sintaxis es : BEGIN { declaracin declaracin declaracin ..... } o BEGIN { declaracin } o BEGIN { declaracin; declaracin; declaracin } Una seccin de declaracin de patrn o cuerpo principal la cual tiene la siguiente sintaxis: patrn { acciones } En esta seccin awk lee un registro del archivo de entrada, y si este cumple con el patrn realiza alguna o algunas acciones con el registro. Algunas formas que pueden aparecer en esta seccin son: /expresin regular / { declaracin } o
______________________________________________________________________________________________ UTM IEC M.C. Gabriel Gernimo Castillo 16
/expresin regular / { declaracin declaracin declaracin ....... } o /expresin regular / { declaracin; declaracin; declaracin } Una seccin END que se ejecuta despus de leer todas las entradas del archivo de datos. Usualmente en esta seccin se realiza los clculos finales, los cuales no pueden ocurrir hasta despus de procesar la entrada de los datos. La sintaxis de esta seccin es: END { declaracin declaracin declaracin ..... } o END { declaracin } o END { declaracin; declaracin; declaracin }
2.3.2 Como ejecutamos programas awk Existen varias formas de ejecutar un programa awk, si el programa es corto, es fcil incluirlo en el comando que ejecuta awk: awk 'PROGRAMA' Archivo-entrada1 Archivo-entrada2 ... donde PROGRAMA consiste de una serie de patrones y acciones. Cuando el programa es largo, es conveniente escribirlo en un archivo y ejecutarlo como sigue: awk -f Archivo-del-PROGRAMA Archivo-entrada1 Archivo-entrada2 ...
$ awk f uno.awk Hola, mundo! Este script slo despliega el mensaje porque la accin se coloco en la seccin de BEGIN. Ejemplo 2: $ cat dos.awk { print Hola mundo! } $ awk f dos.awk Cuando ejecutamos este comando no hace nada hasta que presionemos enter, pero no retorna el prompt del sistema, debemos presionar ^C para retornar al prompt. La razn de esto es que awk necesita de un archivo para aplicar los comando que se encuentran en el cuerpo principal del script, y como no existe archivo de entrada el espera leer una registro hasta que encuentre un enter. Si tenemos por ejemplo un archivo (llammosle nombres) con 5 lneas y lo colocamos como archivo de entrada pasar lo siguiente: $awk f dos.awk nombres Hola, mundo! Hola, mundo! Hola, mundo! Hola, mundo! Hola, mundo! $
2.3.3 Registros y campos Como mencionamos al inicio de la seccin, cada lnea del archivo de entrada es un registro, y cada registro esta formado por campos que se encuentran delimitados por un carcter separador (por default un tab o espacio en blanco). Supongamos que tenemos el siguiente archivo (llamado autos.txt): ES BS AS ES DS ES AS CS Arturo 85 Brenda 90 Sara 91 Sandra 92 Samuel 93 Daniel 86 Norma 89 Mario 90 Honda Nissan BMW Honda Honda VW Porsche VW Prelude 300ZX M-3 Civic CRX-Si GTI 911 Golf 190.00 130.00 345.00 210.00 230.00 90.00 420.00 115.00
Donde cada columna representa la clase, el nombre del conducto, el ao del modelo, el fabricante, el modelo y el precio. Este archivo contiene 8 registros, y cada registro contiene 6 campos. Con estos datos podemos usar awk para calcular el precio de todos los autos, el precio de los autos en cada clase, para todos VW, para todos los del ao 90, etc.. Cada campo en el registro tiene asociado una variable interna de awk, la cual es un valor; para referirnos a este valor debemos utilizar: $0 $1 $2 $n Para el valor del registro de entrada Para el valor del primer campo Para el valor del segundo campo En forma general, representa el valor del n-simo campo.
Ejemplo 3: $cat tres.awk #imprime el nombre del conducto y el fabricante del carro # { print $2 $4 } $awk f tres.awk autos.txt ArturoHonda BrendaNissan SaraBMW SandraHonda SamuelHonda DanielVW NormaPorsche MarioVW Si deseamos colocar un espacio separador entre los valores de los campos debemos colocar en el print una coma entre los campos, pero si queremos que aparezca impresa una coma debemos colocar la coma entre comillas ,. Ejemplo 4: #imprime el nombre del conducto y el fabricante del carro, separados por , # { print $2 , $4 } $awk f tres.awk autos.txt Arturo, Honda Brenda, Nissan Sara, BMW Sandra, Honda Samuel, Honda Daniel, VW
Norma, Porsche Mario, VW Veamos un ejemplo donde utilizamos las tres secciones y utilizamos la variable NR, la cual contiene el numero de registros que fueron ledos, para esto supongamos que tenemos un archivo llamado nombres.txt con diez registros y 5 campos: nombre, apellido paterno, apellido materno, grupo, semestre. Ejemplo 5: $cat grupo.awk BEGIN { print print Clase de redes print } #cuerpo principal del script { print $2, $1 } END { Print Numero de estudiantes: NR } $awk f grupo.awk nombres.txt Salazar Rose Villalba Nancy Cervantes Nashelli Doquis Carlos Benitez Blanca Martnez Beln Luna Lizbeth Lpez Mayra Cruz Martha Ruiz Jos Numero de estudiantes: 10
2.3.4 Variables en awk Awk contiene una serie de variables que proporcionan informacin acerca del tamao y composicin de los registros de entrada, y variables para el control de formato. NR NF FS RS Nmero de registros que fueron ledos. Nmero de campos en el registro actual. Separador de campo de entrada (por default, es un espacio). Separador de registros (por default, newline).
Valor de la entrada actual del registro. Valor del n-simo campo del registro. Separador del campo de salida (por default, espacio). Separador de registro de salida (por default, newline). Nombre del archivo de entrada. Nmero de argumentos en la lnea de comandos. Arreglo de argumentos en la lnea de comandos. Nmero de registros en el archivo actual.
2.3.5 Patrones Para buscar patrones en un archivo se utiliza el carcter de tilde (~). Por ejemplo el siguiente script usa el patrn $1 ~ /AS/ y si lo encuentra imprime el registro completo e incrementa un contador para que en la seccin END imprima el nmero total de claves AS encontradas. Ejemplo 6: # Script que busca el patrn AS en el campo 1 # $1 ~ /AS/ { print $0 num = num + 1 } END { print Fueron encontradas: num AS } Awk usa el smbolo ! para negar una coincidencia o patrn, por ejemplo para mostrar todos los registros que no contengan AS. Ejemplo 7: # Script que encuentra todos los registros que no contengan AS # $1 !~ /AS/ { print $0 num++ } END { print Fueron encontrados : num registros que no contienen AS }
2.3.6 Operadores Awk tiene un conjunto de operadores aritmticos y lgicos similares a los usados en C. En la tabla 2-4 se muestra los operadores aritmticos, y en la tabla 2-5 se muestran los operadores relacionales que son usados para comparar los valores de dos variables.
Tabla 2-4. Operadores aritmticos. Smbolo + Suma Resta * Multiplicacin / Divisin % Operador modulo Tabla 2-5. Operadores relacionales. Smbolo == Igualdad != Desigualdad > Mayor que >= Mayor que o igual que < Menor que <= Menor que o igual que Awk cuenta como ya hemos visto con el operador de asignacin = para colocarle un valor a una variable, aparte de este operador, awk cuenta con operadores de asignacin cortos tomado de C (tabla 2-6), con operadores de incremento (tabla 2-7) y los operadores lgicos && el cual equivale a un and y || el cual representa un or. Tabla 2-6. Operadores de asignacin compuestos Smbolo += Suma y asigna -= Resta y asigna *= Multiplica y asigna /= Divide y asigna %= Modulo y asigna . Tabla 2-7. Operadores de incremento. Smbolo Incrementa en uno Decrementa en uno
++ --
Veamos un ejemplo donde utilizamos el operador lgico &&. Ejemplo 8: # Script que muestra los id que se encuentran entre el intervalo [100,1300) # tomados del archivo passwd, utilizando la variable FS para indicar que la separacin # de los campos es por medio de : BEGIN { FS = : } $3 >= 100 && $3<200 { print }
La declaracin print, es utilizado para imprimir salidas no formateadas. La declaracin printf se utiliza para imprimir salidas formatedas, esta instruccin es similar al printf de C. La sintaxis del printf es: printf formato, expresion1, expresion2, ...
En la tabla 2-8 se muestran los formatos especificados en awk. Tabla 2-8. Conversin de formatos. Especificacin %d %f %o %x %s %e Imprime la salida como un entero decimal (en base 10). Imprime la salida como un valor de punto flotante. Imprime la salida como un valor octal. Imprime la salida como un valor hexadcimal. Imprime la salida como una cadena. Imprime la salida como un punto flotante con notacin cientfica.
Ejemplo 9: # Script para mostrar el uso del printf { printf %s %s \t [ %.2f] \n, $1, $2, $6 }
Ejemplo 10: # Script que utiliza printf y la salida # la redirecciona a un archivo (result.txt) { printf (%s %s \t [%.2f] \n, $1, $2, $6) > result.txt } 2.3.7 Declaraciones condicionales Awk soporta dos tipos de condicionales: implcitas y explicitas. Las condicionales explicitas son: if, if-else cuya sintaxis es: if ( expresin ) accin Si expresin es verdadera entonces la accin se ejecuta if ( expresin ) accin-1 else accin-2 Si el valor de expresin es verdadero entonces accin-1 es ejecutada, sino se ejecuta accin-2. Al igual que en C si la accin involucra ms de una instruccin entonces se utilizan { }.
La sintaxis de una condicin implcita es: Patrn que contiene una expresin relacional { accin } Ejemplo 11: $3 > 1000 { print $3 } 2.3.8 Loops Una de las declaraciones que controlan las repeticiones en awk es while, cuya sintaxis es: while ( expresin ) accin Ejemplo 12: num = 1 costo = 0 while ( num <= 10 ) { costo += $6 num++ } La declaracin do-while proporcionan una ligera diferencia con respecto al while, checa la expresin hasta el final, por lo que la accin por lo menos se ejecuta una vez. do { accin } while ( expresin ) Ejemplo 13: num = 5 costo = 0 do { costo += $3 num - }while ( num > 0 ) La declaracin for es otra forma de loop en awk. Este loop frecuentemente se usa cuando se conoce el nmero de iteraciones a ejecutar. La sintaxis del for es: for ( expr1; expr2; expr3 ) accin Ejemplo 14: costo = 0 for ( num =1; num <= 10; num++)
{ costo += $6 }
2.3.9 Manipulacin de cadenas Awk es una herramienta excelente para manejar cadenas. Las funciones que utiliza se muestran en la tabla 2-9. Tabla 2-9.Funciones de manipulacin de cadenas. Uso Ejemplo Retorna la longitud de una cadena print length ($4) pint substr (Domingo, 1,3) Retorna la subcadena de n caracteres, de la cadena s empezando en la posicin m. Despliega: Dom La sintaxis es: substr (s, m, n). Si se omine n se retorna el resto de la cadena a partir de m. Retorna la posicin de la primera ocurrencia de la cadena t en la cadena s. La sintaxis es: index (s, t) Supongamos que tenemos un archivo de nmeros con punto flotante y queremos obtener slo las centenas. { dp = index ($1, .) print substr ($1, dp + 1 ) } { mensaje = sprintf (Juan tiene %d aos %d meses % das, ao, meses, dia) print mensaje }
index
sprintf
Retorna una cadena completa a partir del formato usado por la declaracin printf.
getline
2.3.10 Funciones matemticas Awk cuenta con varias funciones matemticas, las cuales se muestran en la tabla 2-10. Tabla 2-10. Funciones matemticas. Resultado Retorna la raz cuadrada de un argumento. sqrt (x) Retorna el valor exponencial de un argumento. exp (x) Retorna el logaritmo de base e (natural) de un argumento. log (x) Retorna el seno de un argumento en radianes. sin (x) Retorna el coseno de un argumento en radianes. cos (x) Retorna el valor entero de un argumento. int (25.4567) retorna el valor de 25 Retorna un nmero aleatorio en el rango de (0, 1). rand ( ) Inicializa rand ( )
2.3.11 Arreglos Un arreglo es una variable que puede contener un conjunto de valores, cada valor es almacenado en un miembro o elemento del arreglo y puede ser accesado usando el nombre del arreglo y el ndice. El ndice puede ser un nmero o una cadena, si el ndice es una cadena, el arreglo es llamado un arreglo asociativo. Ejemplo 15: #script awk que muestra como manipular arreglos # BEGIN { printf Script que usa un arreglo } { t[NR] = $1 } END { for ( i=1 ; i<=NR ; i++) { print t[i] } }
2.4 Bibliografa Rod Manis, Marc H. Meyer. Howard W, The UNIX Shell. Programming Languaje, SAMS &Co, 1988. H. M. Deitel, Sistemas Operativos, Addison Wesley, 1999. Kenneth H. Rosen, Richard R. Rosinski, James M. Farber, Douglas A. Host , UNIX. Sistema V, Mc Graw Hill, 1997. Peter Holsberg, UNIX Desktop Guide To Tools, SAMS, 1992. David Medinets, UNIX Shell. Programming Tools, Mc Graw Hill, 1999. Arnold D. Robbins, Effective AWK Programming, Free Software Foundation, 1997.