132
El Lenguaje de Programación AWK/GAWK Una guía de Usuario para AWK Jesús Alberto Vidal Cortés [email protected], http://inicia.es/de/chube Córdoba, Mayo de 2001

AWK Tutorial

Embed Size (px)

Citation preview

  • El Lenguaje de Programacin AWK/GAWK

    Una gua de Usuario para AWK

    Jess Alberto Vidal Corts

    [email protected], http://inicia.es/de/chube

    Crdoba, Mayo de 2001

  • 1. IntroduccinDentro de las herramientas del sistema UNIX awk es equivalente a una

    navaja del ejercito suizo, que es til para modificar archivos, buscar y transformarbases de datos, generar informes simples y otras muchas cosas. awk puede usarsepara buscar un nombre particular en una carta o para aadir un nuevo campo a unabase de datos pequea. Tambin se puede utilizar para realizar el tipo de funcionesque proporcionan muchas de las otras herramientas del sistema UNIX -- buscarpatrones, como egrep, o modificar archivos, como tr o sed --. Pero puesto quetambin es un lenguaje de programacin, resulta ms potente y flexible quecualquiera de ellos.

    awk est especialmente diseado para trabajar con archivos estructuradosy patrones de texto. Dispone de caractersticas internas para descomponer lneas deentrada en campos y comparar estos campos con patrones que se especifiquen.Debido a estas posibilidades, resulta particularmente apropiado para trabajar conarchivos que contienen informacin estructurada en campos, como inventarios, listasde correo y otros archivos de bases de datos simples. Este manal mostrar comoutilizar awk para trabajar con tales tipos de archivos.

    Muchos programas tiles awk solamente son de una lnea de longitud,pero incluso un programa awk de una lnea puede ser el equivalente de unaherramienta regular del sistema UNIX. Por ejemplo, con un programa awk de unalnea puede contarse el nmero de lneas de un archivo (como wc), imprimir elprimer campo de cada lnea (como cut), imprimir todas las lneas que contienen lapalabra (como grep), intercambiar la posicin de los campostercero y cuarto de cada lnea (join y paste) o borrar el ltimo campo de cada lnea.Sin embargo, awk es un lenguaje de programacin con estructuras de control,funciones, y variables. As, si se aprenden rdenes awk adicionales, pueden escribirseprogramas ms complejos.

    El nombre de awk se debe a las iniciales de sus diseadores: Alfred V.Aho, Peter J. Weinberger y Brian W. Kernighan. La versin original de awk fuescrita en 1977 en los Laboratorios de AT&T. En 1985 una nueva versin hizo allenguaje de programacin ms potente, introduciendo funciones definidas por elusuario, mltiples streams de entrada y evaluacin de expresiones regulares. Estanueva versin estuvo disponible de forma general con el Unix System V Release3.1.El Release 4 de System V aadi algunas caractersticas nuevas y tambincorrigi algunos de los agujeros que presentaba el lenguaje.

    La implementacin GNU, gawk, fue escrita en 1986 por Paul Rubin y JayFenlason, con consejos de Richard Stallman. John Woods tambin contribuy conparte del cdigo. En 1988 y 1999, David Trueman, con ayuda de Arnold Robbins,trabajaron duramente para hacer a gawk compatible con el nuevo awk.

  • 2. Empezando con awkLa funcin bsica de awk es buscar lneas en ficheros (u otras unidades de

    texto) que contienen ciertos patrones. Cuando en una lnea se encuentra un patrn,awk realiza las acciones especificadas para dicho patrn sobre dicha lnea. Awk siguerealizando el procesamiento de las lneas de entrada de esta forma hasta que se llegaal final del fichero.

    Cuando ejecutas awk, especificas un programa awk que le dice a awk quetiene que hacer. El programa consiste en una serie de reglas (podra tambin contenerdefiniciones de funciones, pero esa es una caracterstica avanzada, as queignormosla por ahora. Ver la seccin 11. Funciones definidas por el Usuario). Cadaregla especifica un patrn a buscar, y una accin a realizar cuando se encuentre dichopatrn en el registro de entrada.

    Sintcticamente, una regla consiste en un patrn seguido por una accin.La accin se encierra entre llaves para separarlas de los patrones. Las reglas estnseparadas por caracteres newline. Por lo tanto, un programa awk presentara lasiguiente forma:

    patrn { accin }patrn { accin }...

    Un ejemplo muy simpleEl siguiente comando ejecuta un programa awk simple que busca la

    cadena de caracteres foo en el fichero de entrada ListaBBS y si la encuentra laimprime. (Las cadenas de caracteres son normalmente llamadas cadenas. )awk '/foo/ { print $0 }' ListaBBS

    Cuando se encuentran lneas que contengan foo, stas son impresas, yaque print $0 hace que se imprima la lnea actual.

    Habrs advertido las barras, /, alrededor de la cadena foo en elprograma awk. Las barras indican que foo es un patrn para bsqueda. Este tipo depatrn se llama expresin regular, y es cubierta con ms detalle posteriormente (Verla seccin Expresiones Regulares como Patrones). Existen comillas simples alrededordel programa awk para que el shell no interprete el programa como caracteresespeciales de la shell.

    Aqu se muestra lo que este programa imprime:

    fooey 5551234 2400/1200/300 B

  • foot 5556699 1200/300 Bmacfoo 5556480 1200/300 Asabafoo 5552127 1200/300 C

    En una regla awk, o el patrn o la accin puede ser omitida, pero noambos. Si el patrn se omite, entonces la accin se realiza para cada lnea de entrada.Si se omite la accin, la accin por defecto es imprimir todas las lneas queconcuerden con el patrn.

    Por lo que, podramos omitir la accin (la sentencia print y las llaves) en elejemplo anterior, y el resultado sera el mismo: todas las lneas que concuerden con elpatrn foo sern impresas. Por comparacin, la omisin de la sentencia print peromanteniendo las llaves produce una accin vaca que no realiza nada; por lo que nose imprimir ninguna lnea.

    Un ejemplo con dos reglasLa utilidad awk lee los ficheros de entrada lnea a lnea. Para cada lnea,

    awk comprueba todos los patrones de todas las reglas. Si concuerdan varios patronesentonces se ejecutan las distintas acciones de cada patrn, en el orden en queaparecen en el programa awk. Si no concuerda ningn patrn, entonces no se ejecutaninguna accin.

    Despus de ejecutar las acciones de las reglas que concuerden con la lnea(quizs no concuerde ninguna), awk lee la siguiente lnea (aunque existenexcepciones, Ver la seccin La Sentencia next). Esto contina hasta que se alcanza elfinal de fichero.

    Por ejemplo, el programa awk:/12/ { print $0 }/21/ { print $0 }contiene dos reglas. La primera regla tiene la cadena 12 como patrn y realiza laaccin print $0. La segunda regla tiene la cadena 21 como patrn y tambinrealiza la accin print $0. La accion/es de cada regla se encierra entre un par dellaves.

    Este programa imprime cada lnea que contiene o la cadena 12 o lacadena 21. Si una lnea contiene ambas cadenas, sta lnea es impresa dos veces,una vez por cada regla.

    Si ejecutamos este programa sobre nuestros dos ficheros de datos deejemplo, ListaBBS y inventarioenviado (Ver el apndice A Ficheros de Datospara los Ejemplos), como se muestra aqu:awk '/12/ { print $0 }

  • /21/ { print $0 }' ListaBBS inventarioenviadoobtenemos la siguiente salida:

    aardvark 5555553 1200/300 B

    alpo-net 5553412 2400/1200/300 A

    barfly 5557685 1200/300 A

    bites 5551675 2400/1200/300 A

    core 5552912 1200/300 C

    fooey 5551234 2400/1200/300 B

    foot 5556699 1200/300 B

    macfoo 5556480 1200/300 A

    sdace 5553430 2400/1200/300 A

    sabafoo 5552127 1200/300 C

    sabafoo 5552127 1200/300 C

    Jan 21 36 64 620

    Apr 21 70 74 514

    Dese cuenta de que la lnea contenida en ListaBBS que empieza porsabafoo fue impresa dos veces, una vez para cada regla.

    Un ejemplo ms complejoAqu tienes un ejemplo para darte una idea de lo que puede hacer un

    programa awk tpico. Este programa muestra como awk puede ser usado parasumarizar, seleccionar y relocalizar la salida de otra utilidad. En el ejemplo se usancaractersticas que no han sido todava explicadas, as que no te preocupes si noentiendes todos los detalles.

    ls l awk '$5 == "Nov" { sum += $4 } END { print sum }'

    Este comando imprime el nmero total de bytes de todos los ficheros deldirectorio actual que fueron modificados por ltima vez en Noviembre (de cualquierao). (En el C Shell necesitars teclear un punto y coma y despus una barrainvertida al final de la primera lnea; en el Shell de Bourne o el Shell BourneAgainpuedes teclear el ejemplo tal y como se muestra).

    La parte de este ejemplo `ls l` es un comando que te da un listado

  • completo de todos los ficheros de un directorio, incluyendo el tamao del fichero y lafecha. La salida es algo como lo siguiente:

    -rw-r--r-- 1 close 1933 Nov 7 13:05 Makefile

    -rw-r--r-- 1 close 10809 Nov 7 13:03 gawk.h

    -rw-r--r-- 1 close 983 Apr 13 12:14 gawk.tab.h

    -rw-r--r-- 1 close 31869 Jun 15 12:20 gawk.y

    -rw-r--r-- 1 close 22414 Nov 7 13:03 gawk1.c

    -rw-r--r-- 1 close 37455 Nov 7 13:03 gawk2.c

    -rw-r--r-- 1 close 27511 Dec 9 13:07 gawk3.c

    -rw-r--r-- 1 close 7989 Nov 7 13:03 gawk4.c

    El primer campo presenta los permisos de lecturaescritura, el segundocampo contiene los enlaces al fichero, y el tercer campo identifica al propietario delfichero. El cuarto campo contiene el tamao del fichero en bytes. Los campos quinto,sexto y sptimo contienen el mes, el da y la hora, respectivamente, en la cual elfichero fue modificado por ltima vez. Finalmente, el octavo campo contiene elnombre del fichero.

    La expresin $5==Nov de tu programa awk es una expresin quechequea si el quinto campo de la salida generada por ls l es igual a Nov. Cadavez que una lnea presenta la cadena Nov en su quinto campo, se realiza la accin{ sum += $4 }. Esto aade el cuarto campo (el tamao del fichero) a la variablesum. Como resultado, cuando awk ha finalizado la lectura de lneas de entrada, sumes la suma de los tamaos de los ficheros cuyas lneas contuvieron el patrn.

    Despus de que la ltima lnea de la salida generada por ls haya sidoprocesada, se ejecuta la regla END, y el valor de la variable SUM se imprime. Eneste ejemplo, el valor de sum sera 80600.

    Estas tcnicas de awk ms avanzadas sern cubiertas en seccionesposteriores. (Ver la seccin 7. Acciones: Overview). Antes de ensearte laprogramacin de awk ms avanzada, debes saber como awk interpreta tu entrada yvisualiza tu salida. Manipulando campos y usando sentencia print, puedes produciralgunos informes muy tiles y de apariencia espectacular.

    Cmo ejecutar los programas awkHay varias formas de ejecutar un programa awk. Si el programa es corto,

    es ms fcil incluir el programa en el mismo comando que ejecuta awk, de lasiguiente forma:

  • awk program inputfile1 inputfile2 ...

    donde program consiste en una serie de patrones y acciones, segn se describianteriormente.

    Cuando el programa es largo, probablemente preferiras poner el programaen un fichero y ejecutarlo con un comando de la siguiente forma:awk f programfile inputfile1 inputfile2 ...

    Programas de ejecucin rpida (Oneshot Throwaway)Una vez que ests familiarizado con awk, escribirs con frecuencia

    programas simples sobre la marcha para solucionar algo puntual. Puedes escribir elprograma como el primer argumento del comando awk, de la siguiente forma:

    awk programa inputfile1 inputfile2 ...

    donde programa consiste en una serie de patrones y acciones, como se describieronanteriormente.

    Este formato de comando le dice al shell que ejecute awk y use programapara procesar los registros en el fichero(s) de entrada. Aparecen comillas simplesalrededor del programa de forma que el shell no interprete ningn carcter awk comocarcter especial del shell. Esto hace que el shell trate programa por completo comoun nico argumento de awk. Por lo tanto permite que programa tenga una extensinde varias lneas.

    Este formato es tambin til para la ejecucin de programas pequeos ymedios desde shell scripts, porque evita la necesidad de un fichero separado para elprograma awk. Un shell script empotrado en la lnea de comando es ms fiable yaque no hay otros ficheros implicados para que se produzcan fallos.

    Ejecutar awk sin Ficheros de EntradaTambin puedes usar awk sin ficheros de entrada. Si tecleas la siguiente

    lnea de comando:

    awk programa

    entonces awk aplica el programa a la entrada estndar, que en la mayora de loscasos es todo lo que tecleas en el terminal.

    Esto continuar hasta que indiques el final de fichero mediante lacombinacin de teclas Controld.

    Por ejemplo, si tu ejecutas el siguiente comando:awk '/th/'

  • cualquier cosa que teclees a continuacin ser cogido como datos para tu programaawk. Si continas y tecleas los siguientes datos:

    Kathy

    Ben

    Tom

    Beth

    Seth

    Karen

    Thomas

    Controld

    Entonces awk imprime la siguiente salida:

    Kathy

    Beth

    Seth

    como las lneas que contienen el patrn especificado th. Dese cuenta de que noreconoce Thomas como lnea que cumpla el patrn. El lenguaje awk hacedistinciones entre maysculas y minsculas, y busca la concordancia con el patrnexacta. (Sin embargo, puedes evitar esto con la variable IGNORECASE. Ver laseccin Sensibilidad a Maysculas en el Matching.)

    Ejecucin de Programas GrandesAlgunas veces, tus programas awk pueden ser muy grandes. En este caso,

    es ms conveniente poner el programa en un fichero separado. Para decirle a awk queuse ese fichero como programa, se teclea:

    awk f ficherofuente inputfile1 inputfile2 ...

    El f le dice a la utilidad awk que obtenga el programa awk del ficheroficherofuente. Cualquier nombre de fichero puede ser usado como ficherofuente.Por ejemplo, podras poner el programa:/th/

    en el fichero thprog. Entonces este comando:

    awk f thprog

    hace la misma cosa que este otro:

  • awk /th/

    lo cual fue explicado anteriormente (ver seccin Ejecutar awk sin Ficheros deEntrada). Dese cuenta que no necesitas normalmente comillas simples alrededor delnombre del fichero que especificas con f, porque la mayora de los nombres deficheros no contienen ninguno de los caracteres especiales de la shell.

    Si quieres identificar tus ficheros con programas awk como tales, puedesaadir la extensin .awk a los nombres de ficheros. Esto no afecta a la ejecucin deun programa awk, pero hace que el nombre del fichero sea ms legible y fcil delocalizar.

    Programas awk EjecutablesUna vez que hayas aprendido awk, podras querer escribir scripts de awk

    contenidos dentro de un Shell Script ejecutable de Unix, usando el mecanismo descript #!. Puedes hacer esto en sistemas Unix BSD y (algn da) en GNU.

    Por ejemplo, podras crear un fichero texto llamado hola que tuviese losiguiente (donde BEGIN es una caracterstica todava no vista):#! /bin/awk f

    # un programa awk de ejemploBEGIN { print "Hola Mundo" }

    Despus de hacer este fichero ejecutable (con el comando chmod), puedesteclear simplemente:

    hola

    desde el shell, y el sistema ejecutar el awk del mismo modo que si hubiesestecleado:

    awk f hello

    Los scripts de awk auto contenidos (introducidos dentro de un Shell Scriptejecutable de Unix) son tiles cuando quieres escribir un programa que puedaninvocar los usuarios sin que sepan que el programa est escrito en awk.

    Si tu sistema no soporta el mecanismo #!, puedes obtener un efectosimilar usando un shell script regular. Sera algo del estilo a esto:

    : Los dos puntos te aseguran de que este script se ejecuta con el shell de Bourne.awk 'program' "$@"

    Usando esta tcnica, es vital encerrar el program entre comillas simplespara proteger que el programa sea interpretado por el shell.

  • El "$@" hace que el shell se salte todos los argumentos de la lnea decomando al programa awk, sin interpretacin. La primera lnea, que comienza con uncolon, se usa de forma que este shell script funcionar incluso si es invocado por unusuario que use la CShell.

    Comentarios en Programas awkUn comentario es un texto que es incluido en el programa para que dicho

    programa sea ms entendible por los lectores del mismo; no siendo los comentariosrealmente parte del programa. Lo comentarios pueden explicar que es lo que hace elprograma, y cmo lo hace. Prcticamente todos los lenguajes de programacin tienealguna forma para introducir comentarios, ya que hay muchos programas realmentedifciles de entender sin su ayuda extra en forma de comentarios.

    En el lenguaje awk, un comentario comienza con el signo almohadilla, #,y dicho comentario contina hasta el final de la lnea. El Lenguaje awk ignora elresto de una lnea desde el momento que encuentra un carcter #. Por ejemplo,podramos haber puesto lo siguiente en el programa thprog.

    # Este programa encuentra registros que contengan el patrn th. De esta forma

    # es como continuas el comentario en una lnea adicional.

    /th/

    Sentencias frente a Lneas en awkBastante a menudo, cada lnea en un programa awk es una sentencia

    separada o regla separada, como esta:

    awk /12/ { print $0 } /21/ { print $0 } ListaBBS inventarioenviado

    Pero algunas veces una sentencia puede ocupar ms de una lnea, y unalnea puede contener varias sentencias. Puedes partir una sentencias en mltipleslneas insertando un carcter newline (salto de lnea) detrs de alguno de lossiguientes caracteres:

    , { ? : && do elseUn carcter newline el cualquier otro punto es considerado como el final

    de una sentencia.

    Si te gustara partir una nica sentencia en dos lneas en un determinadopunto en el cual un carcter newline terminara dicha sentencia, puedes continuarlafinalizando la primera lnea con un carcter de barra invertida, \. Esto esta permitidoabsolutamente en cualquier sitio de la sentencia, incluso en mitad de una cadena o

  • expresin regular. Por ejemplo:awk '/Este programa es demasiado grande, as que continua \

    en la lnea siguiente / { print $1 }'Nosotros no hemos utilizado, por norma, el uso de la continuacin de una

    lnea mediante la barra invertida en los programas de ejemplo de este manual. Ya queno hay lmite en la longitud de una lnea, nunca es estrictamente necesario particionarsta; es simplemente por cuestin de esttica. La continuacin mediante barrainvertida es muy til cuando tu programa awk est en un fichero fuenteindependiente, en lugar de ser tecleado en la lnea de comandos.

    Precaucin: la continuacin de lnea usando la barra invertida nofunciona tal y como se describe aqu bajo la C Shell. La continuacin con barrainvertida funciona en tus ficheros con programas awk, y tambin en los programasque se lanzan escribindolos directamente en la lnea de comandos teniendo encuenta que ests usando el Bourne shell o Bourneagain Shell. Pero el C shell usadoen Unix Berkeley se comporta de forma diferente! Bajo este Shell, debes usar dosbarras invertidas en una fila, seguido por un carcter newline.

    Cuando las sentencias awk dentro de una regla son cortas, podras desearponer ms de una en una misma lnea. Se puede hacer esto separando las sentenciasmediante puntos y coma ;. Esto se aplica tambin a las mismas reglas. Por lo que, elprograma de ms arriba se podra haber escrito:

    /12/ { print $0 } ; /21/ { print $0 }Nota: el requerimiento de que las reglas en la misma lnea deben ser

    separadas por puntos y comas es un cambio reciente en el Lenguaje awk; fue hechopor consistencia con el tratamiento de las sentencias dentro de una accin.

    Cuando usar awkTe estars preguntando: qu uso le puedo yo dar a todo esto? Utilizando

    programas de utilidades adicionales, patrones ms avanzados, separadores de campo,sentencias aritmticas, y otros criterios de seleccin, puedes producir una salidamucho ms compleja.

    El lenguaje awk es muy til para producir informes a partir de grandescantidades de datos raw, tales como informacin de sumarizacin a partir de la salidade otros programas de utilidades tales como ls. (Ver la seccin Un ejemplo mscomplejo).

    Los programas escritos con awk son a menudo mucho ms pequeos de loque seran en otros lenguajes. Esto hace que los programas awk sean ms fciles decomponer y usar. A menudo los programas awk pueden ser compuestos rpidamenteen tu terminal, usados una y mltiples veces. Debido a que los programas de awk son

  • interpretados, puedes evitar el ciclo de desarrollo de software normal.

    Han sido escritos en awk programas complejos, incluido un completoensamblador para microprocesadores de 8 bits (Ver la seccin 18. Glosario, para msinformacin) y un ensamblador microcodificado para una computadora Prolog depropsito especial. Sin embargo, las posibilidades de awk van ms all de talescomplejidades.

    Si te encuentras a ti mismo escribiendo scripts de awk de ms de, digamos,unos pocos de cientos de lneas, podras considerar usar un lenguaje de programacindiferente. Emacs Lisp es una buena eleccin si necesitas cadenas sofisticadas ocapacidades de bsqueda de patrones. El shell tambin est bien para bsqueda depatrones y cadenas; adems, te permite el potente uso de utilidades del sistema.Lenguajes ms convencionales, tales como C, C++, y Lisp, te ofrecen mejoresfacilidades para la programacin de sistema y para manejar la complejidad degrandes programas.

  • 3. Leyendo ficheros de EntradaEn el programa awk tpico, toda la entrada se lee de la entrada estndar

    (normalmente el teclado) o de los fichero cuyos nombres se especifican en la lnea decomando de awk. Si especificas ficheros de entrada, awk lee los datos del primerfichero hasta que alcanza el final del mismo; despus lee el segundo fichero hasta quellega al final, y as sucesivamente. El nombre del fichero de entrada actual puede serconocido por la variable implcita FILENAME (Ver la seccin 12. VariablesImplcitas (Built-in).

    La entrada se lee en unidades llamadas registros, y stos son procesadospor las reglas uno a uno. Por defecto, cada registro es una lnea del fichero deentrada. Cada registro ledo es dividido automticamente en campos, para que puedanser tratado ms fcilmente por la regla. En raras ocasiones necesitars usar elcomando getline, el cual puede realizar entrada explcita de cualquier nmero deficheros (Ver la seccin Entrada explcita con getline)

    Cmo se particiona la Entrada enRegistros

    El lenguaje awk divide sus registros de entrada en campos. Los registrosestn separados por un carcter llamado el separador de registros. Por defecto, elseparador de registros es el carcter newline. Por lo tanto, normalmente, un registrose corresponde con una lnea de texto. Algunas veces puedes necesitar un carcterdiferente para separar tus registros. Puedes usar un carcter diferente mediante lallamada a la variable empotrada RS (Record Separator).

    El valor de RS es una cadena que dice como separar los registros; el valorpor defecto es \n, la cadena formada por un nico carcter newline. Esta es la raznpor la cual un registro se corresponde, por defecto, con una lnea.

    RS puede tener cualquier cadena como valor, pero solamente el primercarcter de la cadena se usar como separador de registros. El resto de caracteres dela cadena sern ignorados. RS es excepcional en este sentido; awk usa el valorcompleto del resto de sus variables implcitas.

    Puedes cambiar el valor de RS en un programa awk con el operadorasignacin, = (Ver la seccin Expresiones de Asignacin). El nuevo carcterseparador de registros de entrada debera estar entre comillas para que sea unaconstante cadena. A menudo, el momento adecuado para hacer esto es el principio dela ejecucin, antes de procesar ninguna entrada, de modo que el primer registro sealedo con el separador apropiado. Para hacer esto, use el patrn especial BEGIN (Verla seccin Los Patrones Especiales BEGIN y END). Por ejemplo:

  • awk 'BEGIN { RS = "/" } ; { print $0 }' ListaBBScambia el valor de RS a /, antes de leer ninguna entrada. Esta es una cadena cuyoprimer carcter es una barra; como resultado, los registros se separarn por las barras.Despus se lee el fichero de entrada, y la segunda regla en el programa awk (laaccin sin patrn) imprime cada registro. Debido a que cada sentencia print aade unsalto de lnea al final de su salida, el efecto de este programa awk es copiar la entradacon cada carcter barra cambiado por un salto de lnea. Otra forma de cambiar elseparador de registros es en la lnea de comandos, usando la caracterstica asignacinde variable (Ver la seccin 14. Invocacin de awk).awk '...' RS="/" sourcefile

    Esto fija el valor de RS a /, antes de procesar sourcefile.La cadena vaca (una cadena sin caracteres) tiene un significado especial

    como valor de RS: significa que los registros estn separados solamente por lneas enblanco. Ver la seccin Registros de mltiples lneas, para ms detalles.

    La utilidad awk guarda el nmero de registros que han sido ledos hasta elmomento del fichero de entrada actual. Este valor es almacenado en la variableimplcita llamada FNR. Esta variable es inicializada a cero cuando se cambia defichero. Otra variable implcita, NR, es el nmero total de registros de entrada ledosde todos los ficheros. Comienza en cero pero nunca es automticamente reseteada acero.

    Si cambias el valor de RS a mitad de la ejecucin de un programa awk, elnuevo valor se usa para delimitar los registros siguientes, pero el registro que estasiendo procesado en ese momento (y los registros ya ledos) no se ven afectados.

    Examinando camposCuando awk lee un registro de entrada, el registro es automticamente

    separado o particionado por el intrprete en piezas llamadas campos. Por defecto, loscampos son separados por espacios en blanco, al igual que las palabras de una frase.Los espacios en awk significan cualquier cadena de uno o ms espacios y/otabuladores; otros caracteres tales como newline, formfeed, etc que sonconsiderados como espacios en blanco por otros languajes no son considerados comoespacios en blanco por awk.

    El propsito de los campos es facilitar al usuario la referencia a las partesconstituyentes de un registro (tratar las subpartes de un registro). No tienes queusarlos puedes operar con el registro completo si es lo que deseas pero loscampos son los que hacen a los programas awk ms sencillos tan potentes.

    Para referirse a un campo en un programa awk, usas un signo de dlar $,seguido por el nmero de campo que desees. Por lo tanto, $1 se refiere al primer

  • campo, $2 se refiere al segundo, y as sucesivamente. Por ejemplo, supn que losiguiente es una lnea del fichero de entrada:

    This seems like a pretty nice example.

    Aqu el primer campo, o $1, es This; el segundo campo, o $2, es seems;y as sucesivamente. Advierta que el ltimo campo, $7, es example.. Ya que no hayespacios en blanco entre la e y el punto final de la frase ., el punto se consideracomo parte del campo sptimo.

    No importa cuantos campos existan, el ltimo campo de un registro puedeser representado por $NF. Por lo que, en el ejemplo anterior, $NF sera lo mismo que$7, o lo que es lo mismo example.. Si intentas referirte a un campo ms all delltimo, tal como $8 cuando el registro tiene solo 7 campos, obtienes la cadena vaca.

    NF, sin el dlar delante, es una variable implcita cuyo valor es el nmerode campos en el registro actual. $0, lo cual parece un intento de acceder al campocero, es un caso especial: representa el registro de entrada completo. Esto es lo queusaras cuando no estuvieses interesado en campos. Aqu estn algunos ejemplosms:

    awk '$1 ~ /foo/ { print $0 }' ListaBBSEste ejemplo imprime cada registro del fichero ListaBBS cuyo primer

    campo contiene la cadena foo. El operador ~ se le llama operador de encaje,bsqueda o matching (Ver la seccin Expresiones de Comparacin); chequea si unacadena (aqu, el campo $1) encaja con una expresin regular dada. En contraste, elsiguiente ejemplo:awk '/foo/ { print $1, $NF }' ListaBBSbusca foo en el registro completo e imprime el primer y el ltimo campo de cadaregistro de entrada que contenga el patrn foo.

    Referenciar campos sin usar constantesEl nmero de un campo no necesita ser una constante. Cualquier expresin

    del lenguaje awk puede ser usado despus de un $ para referirse a un campo. Elvalor de la expresin especifica el nmero de campo. Si el valor es una cadena, enlugar de un nmero, dicha cadena se convierte a nmero. Considere este ejemplo:awk '{ print $NR }'

    Recuerde que NR es el nmero de registros ledos hasta el momento: 1para el primer registro, 2 para el segundo, etc. As que este ejemplo imprimira elprimer campo del primer registro, el segundo campo del segundo registro, y assucesivamente. Para el registro veinte, se imprimira el campo nmero 20; esprobable que el registro tenga menos de 20 campos, as que imprimira una lnea en

  • blanco.

    Aqu tienes otro ejemplo de la utilizacin de una expresin como nmerode campo:

    awk '{ print $(2*2) }' ListaBBSEl lenguaje awk debe evaluar la expresin (2*2) y usar su valor como el

    nmero del campo a imprimir. El signo * representa multiplicacin, as que laexpresin 2*2 toma el valor 4. Los parntesis son usados para que la multiplicacinse realice antes que la operacin $; son necesarios donde quiera que haya unoperacin binario en la expresin nmero de campo. Este ejemplo, entonces, imprimelas horas de operacin (el cuarto campo) para cada lnea del fichero ListaBBS.

    Si el nmero de campo toma el valor de 0, obtienes el registro entero. Porlo que, $(2-2) tiene el mismo valor que $0. Nmeros de campo negativos no sonpermitidos.

    El nmero de campos en el registro actual se almacena en la variableimplcita NF (Ver la seccin 12. Variables Implcitas (Built-in). La expresin $NF noes una caracterstica especial: es la consecuencia directa de evaluar NF y usar suvalor como nmero de campo.

    Cambiando los contenidos de un campoPuedes cambiar los contenidos de un campo dentro de un programa awk;

    estos cambios que awk percibe como el registro de entrada actual (La entrada real esintocable: awk nunca modifica el fichero de entrada). Mire este ejemplo:awk '{ $3 = $2 - 10; print $2, $3 }' inventarioenviado

    El signo - representa la substraccin, de modo que este programareasigna el campo tres, $3, y le da el valor del campo 2 menos el campo dcimo, $2 -$10. (Ver la seccin Operadores Aritmticos). El campo dos, y el nuevo valor delcampo tres son impresos.

    Para poder realizar esta operacin, el texto del campo dos debe sersusceptible a ser convertido a nmero, la cadena de caracteres debe ser convertida anmero para que se puede realizar la operacin aritmtica sobre dicho campo. Elnmero resultante de la sustraccin se convierte de nuevo a cadena de caracterescuando se convierte en el campo tercero. Ver la seccin Conversiones de Cadenas yNmeros.

    Cuando cambias el valor de un campo (como es percibido por awk), eltexto del registro de entrada es recalculado para contener el nuevo campo en laposicin en la que estaba el antiguo. Por lo tanto, $0 cambia para reflejar el campoalterado. Por lo que,

  • awk '{ $2 = $2 - 10; print $0 }' inventarioenviadoimprime una copia del fichero de entrada, restndole 10 unidades a cada uno de losvalores que presenta el campo 2 para todas las lneas.

    Tambin puedes asignar contenidos a campos que estn fuera del rango.Por ejemplo:awk '{ $6 = ($5 + $4 + $3 + $2) ; print $6 }' inventarioenviado

    Acabamos de crear el campo $6, cuyo valor es la suma de los campos $2,$3, $4, y $5. El signo + representa la suma. Para el fichero inventarioenviado, $6representa el nmero total de objetos embarcados para un mes en particular.

    La creacin de un nuevo campo cambia la copia interna del registro deentrada actual que tiene awk el valor de $0. Por lo que, si realiza un print $0despus de aadir un campo, el registro impreso incluye el nuevo campo, con elnmero de separadores de campo apropiado entre el nuevo campo y los camposexistentes previamente.

    Esta recomputacin afecta y se ve afectada por varias caractersticastodava no discutidas, en particular, el separador de campos de salida, OFS, que seusa para separar los campos (Ver la seccin Separadores de la Salida), y NF (elnmero de campos; Ver la seccin Examinando campos). Por ejemplo, el valor de NFse fija al nmero del campo mayor que hayas creado.

    Anotar, sin embargo, que referenciar a un campo fuera de rango nocambia ni el valor de $0 ni el de NF. El referenciar a un campo fuera de rangoproduce simplemente una cadena nula. Por ejemplo:if ($(NF+1) != "") print "no puede ocurrir"

    else

    print "todo es normal"

    imprimira `todo es normal', ya que NF+1 est fuera de rango ciertamente (Ver laseccin La Sentencia if, para ms informacin sobre las sentencias de awk if-else).

    Especificando como estn separados loscampos

    El modo en el que awk divide los registros de entrada en campos escontrolada por el separador de campo, el cual es un carcter simple o una expresinregular. Awk recorre el registro de entrada en bsqueda de coincidencias delseparador de campos; los campos son el texto que se encuentra entre dichos

  • separadores de campos encontrados. Por ejemplo, si el separador de campos es oo,entonces la siguiente lnea:

    moo goo gai pan

    ser particionada en tres campos: `m', ` g' y ` gai pan'.

    El separador de campos est representado por la variable implcita FS.Que tomen nota los programadores de la Shell! Awk no usa el nombre IFS el cual esusado por la shell. Puedes cambiar el valor de FS en el programa awk con el operadorasignacin, = (Ver la seccin Expresiones de Asignacin). A menudo el momentoadecuado para hacer esto es el principio de la ejecucin, antes de que se proceseninguna entrada, de forma que el primer registro se lea con el separador adecuado.Para hacer esto, use el patrn especial BEGIN (Ver la seccin Los PatronesEspeciales BEGIN y END). Por ejemplo, aqu hemos fijado el valor de la variable FSa la cadena ,:

    awk 'BEGIN { FS = "," } ; { print $2 }'Dada la siguiente lnea,

    John Q. Smith, 29 Oak St., Walamazoo, MI 42139Este programa awk extrae la cadena `29 Oak St.'.

    Algunas veces tus datos de entrada contendrn caracteres separadores queno separen los campos de la forma que tu pensabas que debieran estar separados. Porejemplo, los nombres de personas en el ejemplo que hemos estado usando podratener un ttulo o sufijo acoplado, tal como `John Q. Smith, LXIX'. Para la entrada quecontuviese dicho nombre:

    John Q. Smith, LXIX, 29 Oak St., Walamazoo, MI 42139El programa de ejemplo anterior extraera `LXIX', en lugar de `29 Oak

    St.'. Si estabas esperando que el programa escribiese la direccin, seras sorprendido.As que elige la disposicin de tus datos y separadores de campos cuidadosamentepara prevenir tales problemas.

    Como ya sabes, por defecto, los campos son separados por secuencias deespacios en blanco (espacios y tabuladores), no por espacios simples: dos espacios enuna fila no delimitan un campo vaco. El valor por defecto del separador de camposes una cadena que contiene un nico espacio. Si este valor fuese interpretado de laforma usual, cada carcter espacio separara campos, de forma que dos espacios enuna fila crearan un campos vaco entre ellos. La razn por lo que esto no ocurre esporque un espacio simple como valor de FS es un caso especial: se toma paraespecificar la manera por defecto de deliminar campos.

    Si FS es cualquier otro carcter simple, tal y como ,, cada ocurrencia dedicho carcter separa dos campos. Dos ocurrencias consecutivas delimitan un campo

  • vaco. Si el carcter ocurre al comienzo o al final de la lnea, eso tambin delimita uncampo vaco. El carcter espacio es el nico carcter que no sigue estas reglas.

    Ms generalmente, el valor de FS podra ser una cadena que contuvieseuna expresin regular. Entonces cada coincidencia en el registro de la expresinregular separa campos. Por ejemplo, la asignacin:FS = ", \t"

    hace que cada rea de una lnea de entrada que consista en una coma seguida de unespacio y un tabulador sea un separador de campo (\t representa el tabulador).

    Para un ejemplo menos trivial de una expresin regular, supn que deseasque los espacios simples separen los campos de la misma forma que lo haran unascomas si fuesen usadas. Le podras asignar a FS el valor [ ]. Esta expresin regularconcuerda con un nico espacio y nada ms.

    El valor de FS puede ser fijado en la lnea de comando. Use el argumento-F para hacerlo. Por ejemplo:awk -F, 'program' input-files

    fija FS para que sea el carcter ,. Dese cuenta de que el argumento aparece enmaysculas -F. Esto contrasta con -f, el cual especifica un fichero que contiene unprograma awk. La distincin entre maysculas y minsculas es significativa en lasopciones de comando: las opciones -F y -f no tienen nada que ver la una con laotra. Puedes usar ambas opciones al mismo tiempo para fijar el argumento FS y paradecirle a awk que el programa se encuentra en un determinado fichero.

    Un caso especial, en modo compatibilidad (Ver la seccin 14. Invocacinde awk), si el argumento a -F es t, entonces el FS es fijado al carcter tabulador.(Esto es porque si t tecleas -F\t, sin las comillas, en el shell, el carcter \ eseliminado, de forma que awk supone que t realmente quieres que tus campos estnseparados por tabuladores, y no por ts. Use FS=T en la lnea de comando sideseas realmente que tus campos aparezcan separados por ts.)

    Por ejemplo, utilicemos un fichero de programa awk llamado baud.awkque contiene el patrn /300/, y la accin print $1. Aqu se presenta el programa:/300/ { print $1 }

    Fijemos tambin el valor de FS al carcter -, y ejecute el programa sobreel fichero ListaBBS El siguiente comando imprime una lista de los nombres delbulletin boards que operan a 300 baudios y los tres primeros dgitos de sus nmerosde telfono:

    awk -F- -f baud.awk ListaBBS

    Produce la siguiente salida:

  • aardvark 555

    alpo

    barfly 555

    bites 555

    camelot 555

    core 555

    fooey 555

    foot 555

    macfoo 555

    sdace 555

    sabafoo 555

    Dese cuenta de la segunda lnea de la salida. Si chequeas el ficherooriginal, vers que la segunda lnea presenta lo siguiente:

    alpo-net 555-3412 2400/1200/300 A

    El guon - como parte del nombre del sistema fue utilizado comoseparador de campo, en lugar del guin que apareca en el nmero de telfono queera lo que se pretenda. Esto te demuestra porqu tienes que ser cuidadoso a la horade elegir tus separadores de campo y registro.

    El siguiente programa busca en el fichero de sistema password, e imprimelas entrada de aquellos usuarios que no tiene password:

    awk -F: '$2 == ""' /etc/passwdAqu usamos la opcin -F de la lnea de comando para fijar el separador

    de campo. Advierta que los campos en /etc/passwd estn separados por dos puntos.El segundo campo representa una password de usuario encriptada, pero si el campoest vaco, dicho usuario no tiene password.

    Registros de mltiples lneasEn algunas bases de datos, una sola lnea no puede guardar

    convenientemente la informacin de un registro. En tales casos, puedes usar registrosde lneas mltiples.

    El primer paso para hacer esto es elegir el formato de tus datos: cuando losregistros no vienen definidos como lneas simples, cmo quieres definirlos? qudebera separar los registros?

  • Una tcnica es usar un carcter inusual o cadena para separar los registros.Por ejemplo, podras usar el carcter formfeed (escrito \f en awk, como en C) parasepararlos, haciendo que cada registro fuese una pgina del fichero. Para hacer esto,simplemente fija la variable RS a \f (una cadena que contenga el carcter formfeed)Cualquier otro carcter podra ser usado igualmente, siempre y cuando dicho carcternunca forme parte de los datos posibles de un registro.

    Otra tcnica es tener registros separados por lneas en blanco. Comodispensacin especial, una cadena nula como valor de RS indica que los registrosestarn separados por una o ms lneas en blanco. Si le das a la variable RS el valorcadena nula, un registro siempre acaba en la primera lnea en blanco que encuentra.Y el siguiente registro no comienza hasta que no se encuentra la siguiente lnea queno sea una lnea en blanco no importa cuantas lneas en blanco aparezcan en unafila, son consideradas como un nico separador de registro.

    El segundo paso es separar los campos del registro. Una forma para haceresto es poner cada campo en una lnea por separado: para hacer esto, fija la variableFS a la cadena \n. (Esta expresin regular simple concuerda con un simple carcternewline).

    Otra idea es dividir cada lnea en campos de la forma normal. Esto ocurrepor defecto como resultado de una caracterstica especial: cuando RS se fija a lacadena nula, el carcter newline siempre acta como un separador de campo. Esto esuna adicin a cuales quiera separaciones de campos resultantes de FS.

    Entrada explcita con getlineHasta ahora hemos estado obteniendo nuestros ficheros de entrada desde el

    stream de entrada principal de awk o la entrada estndar (normalmente tu terminal)o los ficheros especificados en la lnea de comandos. El Lenguaje awk tiene uncomando implcito especial llamado getline que puede ser usado para leer la entradabajo tu control explcito.

    Este comando es bastante complejo y no debera ser usado porprincipiantes. Se explica aqu porque este es el captulo de la entrada. Los ejemplosque siguen a la explicacin del comando getline incluyen material que no ha sidoexplicado todava. Por lo tanto, vuelve a estudiar el comando getline despus dehaber visto el manual completo y que tengas un buen conocimiento de cmo funcionaawk.

    El comando getline devuelve un 1 si encuentra un registro, y 0 si seencuentra el final del fichero. Si se produce algn error al obtener un registro, debidopor ejemplo a que dicho fichero no pueda ser abierto, entonces getline devolver un1.

    En los siguientes ejemplos, comando representa una cadena que representa

  • un comando del shell.

    Getline

    El comando getline puede ser usado sin argumentos para leer la entradadel fichero de entrada actual. Todo lo que hace en este caso es leer el siguienteregistro de entrada y dividirlo en campos. Esto es til cuando has acabado deprocesar el registro actual y no vas a realizar ninguna alteracin del mismo y quieresprocesar justo en ese momento el siguiente registro. Aqu tienes un ejemplo:awk '{ if (t = index($0, "/*")) { if(t > 1) tmp = substr($0, 1, t - 1) else

    tmp = ""

    u = index(substr($0, t + 2), "*/") while (! u) { getline

    t = -1

    u = index($0, "*/") } if(u

  • Ver la seccin Examinando campos), NR (el nmero de registros ledos hasta ahora,Ver la seccin Cmo se particiona la Entrada en Registros), FNR (el nmero deregistros ledos del fichero de entrada actual), y el valor de $0.

    Nota: el nuevo valor de $0 se usa en el chequeo de los patrones de lasreglas subsiguientes. El valor original de $0 que dispar la regla que ejecut getlinese pierde. Por contraste, la sentencia next lee un nuevo registro pero inmediatamentecomienza a procesarlo normalmente, comenzando con la primera regla del programa.Ver la seccin La Sentencia next.

    Getline variable

    Esta forma de getline lee un registro en la variable variable. Esto es tilcuando quieres que tu programa lea el siguiente registro del fichero de entrada actual,pero no quieres someter el registro que leas al procesamiento de la entrada normal.

    Por ejemplo, supn que la siguiente lnea es un comentario, o una cadenaespecial, y quieres leerla, pero quieres realizar lo que sea que no dispare ningunaregla. Esta versin de getline te permite leer esa lnea y almacenarla en una variablede forma que el bucle principal de leer una lnea y chequearla contra todas las reglasnunca llega a conocer dicha lnea.

    El siguiente ejemplo alterna (swaps) cada dos lneas de entrada. Porejemplo, dado:wan

    tew

    free

    phore

    produce la siguiente salida:

    tew

    wan

    phore

    free

    Aqu tienes el programa:

    awk '{ if ((getline tmp) > 0) { print tmp

    print $0

  • } else print $0}'

    La funcin getline usada de esta forma fija solamente las variables NR yFNR ( y por supuesto, variable). El registro no es dividido en campos, de forma quelos valores de los campos (incluyendo $0) y el valor de la variable NF no cambia.getline < fichero

    Esta forma de la funcin getline toma su entrada desde el fichero fichero.Aqu fichero es una expresin que se trata como una cadena que contiene el nombredel fichero. A la expresin

  • En esta versin de getline, ninguna de las variable implcitas cambia suvalor, y el registro no es dividido en campos. La nica variable que cambia esvariable. Por ejemplo, el siguiente programa copia todos los ficheros de entrada a lasalida, excepto los registros que dicen `@include nombre_fichero'. Tales registrosson reemplazados por el contenido del fichero nombre_fichero.awk '{ if (NF == 2 && $1 == "@include") { while ((getline line < $2) > 0) print line

    close($2) } else print

    }'Advierta aqu como el nombre del fichero de entrada extra no se construye

    en el programa; es cogido de los datos, del segundo campo de las lneas @include.

    La funcin close se llama para asegurarse que si aparecen dos lneas@include idnticas, el fichero especificado entero se incluye dos veces. Ver laseccin Cerrado de Ficheros de Entrada y Pipes.

    Una deficiencia de este programa es que no procesa las sentencias@include anidadas del mismo modo que un preprocesador de macros hara.

    comando getlinePuedes hacer un pipe de la salida a un comando a getline. Un pipe es

    simplemente una forma de enlazar la salida de un programa con la entrada de otro.En este caso, la cadena comando es ejecutada como un comando de la shell y susalida es pipeada dentro de awk para que sea usado como entrada. Esta forma degetline lee un registro del pipe.

    Por ejemplo, el siguiente programa copia la entrada a la salida, excepto laslneas que comienzan con @execute, las cuales son reemplazadas por la salidaproducida por la ejecucin del resto de la lnea como un comando de shell:awk '{ if ($1 == "@execute") { tmp = substr($0, 10) while ((tmp getline) > 0)

  • print

    close(tmp) } else print

    }'La funcin close se usa para asegurarse de que si aparecen dos lneas

    @execute idnticas, el comando se ejecute de nuevo para cada lnea. Ver la seccinCerrado de Ficheros de Entrada y Pipes.

    Dada la siguiente entrada:

    foo

    bar

    baz

    @execute who

    bletch

    el programa podra producir:

    foo

    bar

    baz

    hack ttyv0 Jul 13 14:22

    hack ttyp0 Jul 13 14:23 (gnu:0)hack ttyp1 Jul 13 14:23 (gnu:0)hack ttyp2 Jul 13 14:23 (gnu:0)hack ttyp3 Jul 13 14:23 (gnu:0)bletch

    Dese cuenta de que este programa ejecut el comando who e imprimi elresultado.

    Esta variacin de getline divide el registro en campos, fija el valor de NF yrecalcula el valor de $0. Los valores de NR y FNR no son cambiados.comando getline variable

  • La salida del comando comando se enva a travs de un pipe a getline y ala variable variable. Por ejemplo, el siguiente programa lee la hora y da actual a lavariable tiempo_actual, usando la utilidad llamada date, y despus la imprime.

    awk 'BEGIN { "date" getline tiempo_actual close("date") print "Report printed on " tiempo_actual

    }'En esta versin de getline, ninguna de las variable implcitas es cambiada,

    y el registro no se divide en campos.

    Cerrado de Ficheros de Entrada y PipesSi se usa el mismo nombre de fichero o el mismo comando shell se usa

    con getline ms de una vez durante la ejecucin de un programa awk, el fichero esabierto (o el comando es ejecutado) slo la primera vez. En ese momento, el primerregistro de la entrada es ledo de ese fichero o comando. La prxima vez que se useese mismo nombre de fichero o comando con getline, otro registro se leer de l, yas sucesivamente.

    Esto implica que si quieres comenzar la lectura del mismo fichero desde elprincipio, o si quieres volver a ejecutar un comando (en lugar de leer ms salida delcomando), debes realizar unos pasos especiales. Lo que puedes usar es la funcinclose, tal y como sigue:

    close(fichero)o

    close(comando)El argumento fichero o comando puede ser cualquier expresin. Su valor

    debe ser exactamente el mismo que la cadena que fue usada para abrir el fichero ocomenzar el comando por ejemplo, si abres un pipe con esto:"sort -r names" getline fooentonces debes cerrar el pipe de esta forma:

    close("sort -r names")Una vez que se ejecuta esta llamada a la funcin, el siguiente getline de

    ese fichero o comando reabrir el fichero o reejecutar el comando.

  • 4. Imprimiendo la SalidaUna de las cosas ms corrientes que realizan las acciones es sacar o

    imprimir parte o toda la entrada. Para salida simple, utilice la sentencia print. Para unformateo ms elegante utilice la sentencia printf. Ambas son descritas en estecaptulo.

    La sentencia printLa sentencia print realiza la salida con un formato estandarizado y simple.

    T especificas solamente las cadenas o nmeros que van a ser impresos, en una listaseparada por comas. Ellos son impresos separados por espacios en blanco, seguidospor un carcter newline o retorno de carro. La sentencia presenta la siguiente forma:

    print item1, item2,

    La lista completa de items podra ser opcionalmente encerrada entreparntesis. Los parntesis son necesarios si algunos de las expresiones items utilizaun operador relacional; por que si no, podra ser confundido con unredireccionamiento (ver la seccin Redireccionando la Salida de print y printf). Losoperados relacionales son ==, !=, , >=,

  • Ejemplos de sentencias printAqu aparece un ejemplo de impresin de una cadena que contiene

    caracteres de retorno de carro o nueva lnea empotrados:

    awk 'BEGIN { print "lnea uno\nlnea dos\nlnea tres" }'produce una salida como esta:

    lnea uno

    lnea dos

    lnea tres

    Aqu tienes un ejemplo que imprime los dos primeros campos de cadaregistro de entrada, con un espacio entre ellos:

    awk '{ print $1, $2 }' inventarioLa salida presentara la siguiente forma:

    Jan 13

    Feb 15

    Mar 15

    Un error comn en el uso de la sentencia print es omitir la coma entre dositems. Esto a menudo produce el efecto de imprimir los dos valores sin separar por unespacio en blanco. La razn de esto es que la yustaposicin de dos expresiones tipocarcter en awk realiza la concatenacin de ellas. Por ejemplo, sin la coma:awk '{ print $1 $2 }' inventarioimprime:

    Jan13

    Feb15

    Mar15

    Debido a que esta salida no le resultara informativa a la gente que noconociese el contenido del fichero invertario, una lnea de cabecera al principioaclarara mucho dicha salida. Aadamos pues, una cabecera a nuestro listado demeses ($1) y canastas verdes enviadas ($2). Nosotros hacemos esto usando el patrnBEGIN (ver la seccin Los Patrones Especiales BEGIN y END) para hacer que la

  • cabecera sea impresa una sola vez:

    awk 'BEGIN { print "Meses Canastas" print "----- --------" } { print $1, $2 }' inventario

    Has conseguido averiguar qu ocurre? El programa imprime lo siguiente:

    Meses Canastas

    ----- --------

    Jan 13

    Feb 15

    Mar 15

    Las cabeceras y las lneas de detalle no estn alineadas! Podemos arreglaresto imprimiendo algunos espacios en blanco entre los dos campos:

    awk 'BEGIN { print "Meses Canastas" print "----- --------" } { print $1, " ", $2 }' inventario

    Puedes imaginar que esta forma de alineacin de columnas se puedevolver realmente complicado cuando tienes que cuadrar muchas columnas. Contar losespacios para dos o tres columnas puede ser simple, pero con ms de tres columnas tepuedes perder bastante faclmente. Este es el motivo por el que se cre la sentenciaprintf (Ver la seccin Uso de sentencias printf para una impresin ms elegante); unade sus especialidades es la de alinear las columnas de datos.

    Separadores de la SalidaComo se mencion anteriormente, una sentencia print contiene una lista de

    items, separados por comas. En la salida, los items son separados normalmente porsimples espacios en blanco. Pero esto no tiene por que ser as; el espacio essolamente el separador por defecto. Puedes especificar cualquier cadena de caracterespara usarla como el separador de campos de salida fijando la variable implcita OFS.El valor inicial de esta variable es la cadena .

    La salida completa de una sentencia print se le llama registro de salida.Cada sentencia print imprime un registro de salida y despus imprime una cadenallamada el separador de registros de salida. La variable implcita ORS determina

  • esta cadena. El valor inicial de la variable es la cadena \n o lo que es lo mismo elcarcter newline, por lo que, normalmente cada sentencia print crea una lnea distinta.

    Puedes cambiar como se separan los campos y registros de salida,asignndoles nuevos valores a las variables OFS y/o ORS. La sitio normal para haceresto es en la regla BEGIN (Ver la seccin Los Patrones Especiales BEGIN y END),de modo que tomen sus valores antes de que se procese ninguna entrada. Tambinpodras hacer esto con asignaciones en la lnea de comando, antes de los nombres detus ficheros de entrada.

    El siguiente ejemplo imprime el primer y segundo campo de cada registrode entrada separados por un punto y coma, aadindole una lnea en blanco adicionaldespus de cada registro en la salida:

    awk 'BEGIN { OFS = ";"; ORS = "\n\n" } { print $1, $2 }' ListaBBS

    Si el valor de ORS no contiene un carcter newline, toda tu salida segenerar a una nica lnea, a menos que pongas saltos de lnea de alguna otra forma.

    Uso de sentencias printf para unaimpresin ms elegante

    Si quieres un control ms preciso sobre el formato de la salida del que teda la sentencia print, utilice printf. Con printf puedes especificar el ancho a utilizarcon cada item, y puedes seleccionar entre varias elecciones de estilo para nmeros(tales como qu radix usar, si imprimir un exponente, si imprimir un signo, ycuando dgitos imprimir despus del punto decimal). Haces esto especificando unacadena, llamada la cadena de formato, la cual controla como y donde imprimir losotros argumentos.

    Introduccin a la sentencia printfLa sentencia printf presenta la siguiente sintxis:

    printf formato, item1, item2,

    La lista completa de items podra ser opcionalmente encerrada entreparntesis. Los parntesis son necesarios si cualquiera de las expresiones item utilizaun operador relacional, de otra forma podra ser confundido con una redireccin (Verla seccin Redireccionando la Salida de print y printf). Los operadores relacionalesson ==, !=, , >=,

  • expresin cuyo valor se toma como una cadena; su funcin es especificar como sedeben imprimir cada uno de los otros argumentos. Se le llama la cadena de formato.

    La cadena de formato es esencialmente que la que se usa para la funcinprintf de la librera de C. La mayora del formato es texto para que sea impresoliteralmente. Pero en medio del texto que debe ser impreso literalmente aparecenespecificadores de formato, uno por item. Cada especificador de formato especificael formato de salida del item o parmetro correspondiente

    La sentencia printf no aade automticamente un carcter newline a susalida. No imprime ninguna otra cosa que lo especificado en el formato. De formaque si quieres un carcter newline, debes incluir uno en el formato. Las variables deseparacin de la salida OFS y ORS no tienen efecto sobre las sentencias printf.

    Letras para el control de formatoUn especificador de formato comienza con el carcter % y acaba con una

    letra de control de formato, y le indica a la sentencia printf como imprimir el itemcorrespondiente (Si realmente quieres imprimir un carcter %, escribe %%). Laletra de control de formato especifica el tipo de valor a imprimir. El resto delespecificador de formato est compuesto de modificadores opcionales los cuales sonparmetros tales como el ancho de campo a usar.

    Aqu tienes una lista de letras de control de formato:

    c

    Esto imprime un nmero como un carcter ASCII. Por lo que, `printf "%c", 65'imprimira la letra A. La salida para un valor cadena es el primer carcter de lacadena.

    d

    Esto imprime un entero decimal.

    i

    Esto tambin imprime un entero decimal.

    e

    Esto imprime un nmero en notacin cientfica (exponencial). Por ejemplo,printf "%4.3e", 1950

    imprime 1.950e+03, con un total de 4 cifras significativas de las cuales 3 siguen alpunto decimal. Los modificadores 4.3 son descritos ms abajo.f

    Esto imprime un nmero en notacin punto flotante.

  • g

    Esto imprime en notacin cientfica o en notacin punto flotante, la que quiera quesea ms corta.

    o

    Esto imprime un entero octal sin signo.

    s

    Esto imprime una cadena.

    x

    Esto imprime un entero hexadecimal sin signo.

    X

    Esto imprime un entero hexadecimal sin signo. Sin embargo, para los valores entre10 y 15, utiliza las letras desde la A a la F en lugar de esas mismas letras pero enminsculas.

    %

    Esta no es realmente una letra de control de formato. Pero tiene un significadoespecial cuando se usa despus de un %: la secuencia %% imprime el carcter%. No consume ni necesita ningn item o argumento correspondiente.

    Modificadores para los formatos de printfUna especificacin de formato tambin puede incluir modificadores que

    controlan como son impresos los valores de los items y cuanto espacio ocuparn. Losmodificadores vienen entre el signo % y la letra de control de formato. Aqu estnlos posibles modificadores, en el orden en el cual podran aparecer:

    El signo menos, usado antes del modificador de ancho, especifica que sejustifique a la izquierda el argumento dentro de la anchura especificada.Normalmente el argumento se ajusta a la derecha dentro del ancho especificado. Porlo que,

    printf "%4s", "foo"

    imprime foo .

    ancho

    Este es un nmero que representa el ancho deseado para un campo. Lainsercin de cualquier nmero entre el signo % y el carcter de control de formato

  • fuerza a que el campo se expanda a este ancho. El modo por defecto para hacer estoes rellenando con espacios en blanco por la izquierda. Por ejemplo,printf "%4s", "foo"

    imprime foo.

    El valor de ancho es un ancho mnimo, no un mximo. Si el valor del itemrequiere ms de ancho caracteres, podr ser tan ancho como necesite. Por lo que,

    printf "%4s", "foobar"

    imprime foobar. Precediendo el ancho con un signo menos hace que la salida searellena con espacios en blanco por la derecha, en lugar de por la izquierda.

    .precisin

    Este es un nmero que especifica la precisin que se debe usar cuando seimprima. Esto especifica el nmero de dgitos que quieres imprimir a la derecha delpunto decimal. Para una cadena, especifica el nmero mximo de caracteres que seimprimirn de dicha cadena.

    La capacidad de ancho y precisin dinmicos de la sentencia printf de lalibrera de C (por ejemplo, "%*.*s") todava no est soportada. Sin embargo, sepuede simular facilmente usando la concatenacin para construir dinmicamente lacadena de formato.

    Ejemplos de Uso de printfAqu tienes como usar printf para presentar una tabla alineada:

    awk '{ printf "%10s %s\n", $1, $2 }' ListaBBSimprime los nombres de los bulletin boards ($1) del fichero ListaBBS como unacadena de 10 caracteres justificados a la izquierda. Tambin imprime los nmeros detelfono ($2) a continacin en la lnea. Esto produce una tabla alineada de doscolumnas de nombres y nmeros de telfonos:

    aardvark 5555553

    alponet 5553412

    barfly 5557685

    bites 5551675

    camelot 5550542

    core 5552912

    fooey 5551234

  • foot 5556699

    macfoo 5556480

    sdace 5553430

    sabafoo 5552127

    Te diste cuenta de que no especificamos que se imprimiesen los nmerosde telfono como nmeros? Tienen que ser impresos como cadenas debido a queestn separados por medio con el guin. Este guin podra ser interpretado como unsigno menos si hubiesemos intentado imprimir los nmeros de telfono comonmeros. Esto nos hubieses producido unos resultados confusos y errneos.

    No hemos especifado un ancho para los nmeros de telfono porque son loltimo que se imprimir en cada lnea. No necesitamos poner espacios despus deellos.

    Podramos haber hecho nuestra tabla ms elegante incluso aadindolecabeceras encima de cada una de las columnas. Para hacer esto, usa el patrnBEGIN(Ver la seccin Los Patrones Especiales BEGIN y END) para hacer que seimprima la cabecera solamente una vez, al principio del programa awk:

    awk 'BEGIN { print "Nombre Nmero" print "------ ------" } { printf "%10s %s\n", $1, $2 }' ListaBBS

    Te diste cuenta de que mezclamos las sentencias print y printf en elejemplo anterior? Podramos haber utilizado solamente sentencias printf para obtenerel mismo resultado:

    awk 'BEGIN { printf "%10s %s\n", "Name", "Number" printf "%10s %s\n", "----", "------" } { printf "%10s %s\n", $1, $2 }' ListaBBS

    Poniendo cada cabecera de columna con la misma especificacin deformato usada para los elementos, nos hemos asegurado que las cabeceras tendrn lamisma alineacin que las columnas. El hecho de que la misma especificacin deformato se use tres veces, puede ser resumido almacenando dicha especificacin deformato en una variable, tal y como sigue:

    awk 'BEGIN { format = "%10s %s\n" printf format, "Name", "Number"

    printf format, "----", "------" } { printf format, $1, $2 }' ListaBBS

  • Redireccionando la Salida de print yprintf

    Hasta ahora hemos estado tratando solamente con salida que imprime en lasalida estndar, normalmente tu terminal. Se les puede decir tanto a print como aprintf que enven su salida a otros sitios. Esto recibe el nombre de redireccin.

    Una redireccin aparece despus de la sentencia print o printf. Lasredirecciones en awk son escritas del mismo modo que se hacen las redirecciones enlos comandos de la shell, excepto que son escritas dentro del programa awk.

    Redireccionando la Salida a Ficheros y PipesAqu aparecen las tres formas de la redireccin de la salida. Ellas se

    muestran todas para la sentencia print, pero funcionan de forma idntica para printf.

    print items > ficherosalida

    Este tipo de redireccin imprime los items en el fichero de salidaficherosalida. El nombre del fichero ficherosalida puede ser cualquier expresin.Su valor se convierte a cadena y despus es usada como nombre de fichero. (Ver laseccin 7. Acciones: Expresiones).

    Cuando se usa este tipo de redireccin, el ficherosalida es eliminadoantes de que se escriba en l la primera salida. Las escrituras siguientes no borrarn elficherosalida, pero s aadirn a l. Si ficherosalida no existe entonces ser creado.

    Por ejemplo, aqu aparece como un programa awk puede escribir una listade nombres BBS a un fichero listanombres y una lista de nmeros de telfonos aun fichero listatelfonos. Cada fichero de salida contiene un nombre o nmero porlnea.

    awk '{ print $2 > "listatelfonos" print $1 > "listanombres" }' ListaBBSprint items >> ficherosalida

    Este tipo de redireccin imprime los items en el fichero de salidaficherosalida. La diferencia entres este y el signo > nico es que los viejoscontenidos (si los tuviese) del fichero ficherosalida no son eliminados. En su lugar,la salida que genera awk es aadida a dicho fichero.

    print items comandoTambin es posible enviar la salida a travs de un pipe en lugar de a un

    fichero. Este tipo de redireccionamiento abre un pipe a comando y escribe los valores

  • de items a travs de este pipe, a otro proceso creado para ejecutar comando.El argumento de redireccin comando es realmente una expresin awk. Su

    valor se convierte a cadena, cuyo contenido nos proporcina el comando de shell quedebe ser ejecutado.

    Por ejemplo, este produce dos ficheros, una lista sin ordenar de nombresBBS y una lista ordenada en orden alfabtico inverso:

    awk '{ print $1 > "names.unsorted" print $1 "sort r > names.sorted" }' ListaBBS

    Aqu la lista desordenada se escribe con una redireccin normal mientrasque la lista ordenada es escrita mediante un pipe al comando sort de Unix.

    Aqu tienes un ejemplo que usa el redireccionamiento para enviar unmensaje a una lista de correos bugsystem. Esto podra ser til cuando seencuentran problemas en un script awk que se ejecuta peridicamente para elmantenimiento del sistema.

    print "Awk script failed:", $0 "mail bugsystem"print "at record number", FNR, "of", FILENAME "mail bugsystem"close("mail bugsystem")

    Llamamos a la funcin close aqu porque es una buena idea cerrar latubera o pipe tan pronto como toda la salida ha pasado a travs de ella.

    El redireccionamiento de la salida usando >, >>, o le pide al sistemaque abra un fichero o pipe solo si el fichero o comando particular que hasespecificado no ha sido ya escrito por tu programa.

    Cerrando los Ficheros de Salida y PipesCuando se abre un fichero o pipe, el nombre de fichero o comando

    asociado con l es recordado por awk y las siguientes escrituras al mismo fichero ocomando son aadidas a las escrituras previas. El fichero o pipe permanece abiertohasta que finaliza el programa awk. Esto es normalmente conveniente.

    Algunas veces existe una razn para cerrar un fichero de salida o un pipeantes de que finalice el programa awk. Para hacer esto, utilice la funcin close, tal ycomo sigue:

    close(nombrefichero)o

    close(comando)

  • El argumento nombrefichero o comando puede ser cualquier expresin.Su valor debe concordar exactamente con la cadena usada para abrir el fichero o pipecuando se empez a usar por ejemplo, si abres un pipe con esto:print $1 "sort r > names.sorted"entonces debes cerrarlo con esto:

    close("sort r > names.sorted")Aqu estn algunas razones por las cuales podras necesitar cerrar un

    fichero de salida:

    Para escribir un fichero y leer el mismo posteriormente en el mismo programaawk. Cierra el fichero cuando hayas acabado de escribir en l; entonces ya puedesempezarlo a leer con getline.

    Para escribir numerosos ficheros, sucesivamente, en el mismo programa awk.Si no cierras los ficheros, eventualmente exceders el lmite del sistema en el nmerode ficheros abiertos por un proceso. As que cierra cada uno cuando hayas acabado deescribirlo.

    Para hacer que un comando acabe. Cuando redireccionas la salida a travs deun pipe, el comando que lee del pipe normalmente sigue intentando leer entradamientras el pipe est abierto. A menudo esto significa que el comando no puederealizar su trabajo hasta que el pipe es cerrado. Por ejemplo, si redireccionas la salidaal programa mail, el mensaje no se enviar realmente hasta que el pipe se cierre. Para ejecutar el mismo programa una segunda vez, con los mismosargumentos. Esto no es la misma cosa que darle ms entrada a la primera ejecucin!

    Por ejemplo, supn que haces un pipe de la salida al programa mail. Sisacas varias lneas redirigidas a este pipe sin cerrarlo, crear un mensaje de variaslneas. En constraste, si cierras el pipe despus de cada lnea de salida, entonces cadalnea creara un correo distinto.

    Streams de Entrada/Salida EstndardLa ejecucin convencional de programa tiene tres streams de entrada y

    salida disponibles para lectura y escritura. Estos son conocidos como la entradaestndar, salida estndar y salida del error estndar. Estos streams son, por defecto,entrada y salida por terminal, pero son a menudo redireccionados con el shell, atravs de los operadores , >& y . El error estndar se usasolamente para la escritura de mensajes de error; la razn por la cual tenemos dosstreams separadas, salida estndar y error estndar, es para que puedan serredireccionados independientemente. En otras implementaciones de awk, la nicaforma de escribir un mensaje de error al error estndar en un programa awk es lasiguiente:

  • print "Serious error detected!\n" "cat 1>&2"Esto trabaja abriendo un pipeline a un comando del shell el cual puede

    acceder a la stream del error estndar. Esto est lejos de ser elegante, y tambin esineficiente, ya que requiere un proceso separado. Por lo que la gente que escribeprogramas awk se han negado a menudo a hacer esto. En su lugar, han enviado losmensajes de error al terminal, tal y como sigue:NF != 4 { printf("line %d skipped: doesn't have 4 fields\n", FNR) > "/dev/tty"}

    Esto tiene el mismo efecto la mayora de las veces, pero no siempre:aunque el stream del error estandrd es normalmente el terminal, puede serredireccionado, y cuando eso ocurre, la escritura al terminal no es lo correcto. Dehecho, si awk se ejecuta desde un trabajo en background, podra no tener un terminalpara poner la salida de dicho error. Entonces, abrir el dispositivo /dev/tty fallara.

    Gawk proporciona nombres de ficheros especiales para acceder a los tresstreams estndar. Cuando redireccionas la entrada o la salida en gawk, si el nombrede fichero encaja con uno de estos nombres especiales, entonces gawk utilizadirectamente el stream con el que se corresponde.

    /dev/stdin

    La entrada estndar (descriptor de fichero 0)./dev/stdout

    La salida estndar (descriptor de fichero 1)./dev/stderr

    La salida del error estndar (descriptor de fichero 2)./dev/fd/n

    El fichero asociado con el descriptor n. Tal fichero debera haber sido abierto por elprograma que inicie la ejecucin awk (normalmente el shell). A menos que hagasalgo para que no sea as, solamente los descriptores 0, 1 y 2 estn disponibles.

    Los nombres de ficheros /dev/stdin, /dev/stdout, y /dev/stderr sonalias para /dev/fd/0, /dev/fd/1, y /dev/fd/2, respectivamente, pero los primerosnombres son ms indicativos.

    La forma ms correcta para escribir un mensaje de error en un programaawk es usar /dev/stderr, algo como esto:

    NF != 4 {

  • printf("line %d skipped: doesn't have 4 fields\n", FNR) > "/dev/stderr"}

    El reconocimiento de estos nombres de fichero especiales es deshabilitadosi awk est en modo compatibilidad (Ver la seccin 14. Invocacin de awk).

  • 5. Programas de "Una lnea"tiles

    Programas de awk tiles son a menudo cortos, de una sola lnea o dos.Aqu tienes una coleccin de programas cortos y tiles para empezar. Algunos deestos programas contienen construcciones que no han sido explicadas todava. Ladescripcin del programa te dar una idea de qu es lo que hace, pero por favor lee elresto del manual para convertirte en un experto de awk.

    awk { num_campos = num_campos + NF }END { print num_campos }

    Este programa imprime el nmero total de campos de todas las lneas deentrada.

    awk length($0) > 80Este programa imprime todas las lneas que tengan ms de 80 caracteres.

    La nica regla tiene una expresin relacional como su patrn, y no tiene ningunaaccin (as que la accin por defecto, imprimir el registro, es la que se usa)awk NF > 0

    Este programa imprime todas las lneas que tienen al menos un campo.Esta es una forma fcil de eliminar lneas en blanco de un fichero (o en su lugar,crear un nuevo fichero similar al fichero anterior pero en el cual se han suprimido laslneas en blanco)awk { if (NF > 0) print }

    Este programa tambin imprime todas las lneas que tienen al menos uncampo. Aqu nosotros aplicamos la regla para buscar la lnea y a continuacin sedecide en la accin donde imprimir.

    awk BEGIN { for (i = 1; i

  • Este programa imprime la mxima longitud de lnea de fichero. El ficherode entrada que va a procesar awk es filtrado previamente con el comando expand quecambia los tabuladores por espacios en blanco, as que las longitudes comparadas sonrealmente las columnas del margen derecho.

  • 6. PatronesLos patrones en awk controlan la ejecucin de reglas: una regla es

    ejecutada cuando su patrn concuerda (matches) con el registro de entrada actual.Este captulo habla sobre como escribir patrones.

    Tipos de PatronesAqu se presenta un sumario de los tipos de patrones soportados en awk.

    /expresin regular/

    Una expresin regular como patrn. Encaja cuando el texto del registro de entradaconcuerda con la expresin regular. (Ver la seccin Expresiones Regulares comoPatrones).expresin

    Una expresin solamente. Casa cuando su valor, convertido a nmero, es distinto decero (si es un nmero) o no nulo (si es una cadena). (Ver la seccin Expresionescomo Patrones).pat1, pat2

    Un par de patrones separados por una coma, especificando un rango de registros.(Ver la seccin Especificando Rangos de Registros con Patrones).BEGIN

    END

    Patrones especiales para suministrar a awk informacin para antes del inicio delprocesamiento o al final del procesamiento. (Ver la seccin Los Patrones EspecialesBEGIN y END).null

    El patrn vaco casa con todos y cada uno de los registros de entrada. (Ver la seccinEl Patrn Vaco).

    El Patrn VacoUn patrn vaco se considera que casa con todos los registros de la

    entrada. Por ejemplo, el programa:awk '{ print $1 }' ListaBBS

  • imprime solamente el primer campo de cada registro.

    Expresiones Regulares como PatronesUna expresin regular, o expreg, es una forma de describir una clase de

    cadenas de texto. Una expresin regular encerrada entre barras (/) es un patrn awkque casa con cada registro de entrada cuyo texto pertenece a esa clase.

    La expresin regular ms simple es una secuencia de letras, nmeros, oambos. Tales expresiones regulares casa con cualquier cadena que contenga dichasecuencia de letras y nmeros. Por lo que, la expresin regular foo casa concualquier cadena que contenga foo. Por lo tanto, el patrn /foo/ casa con cualquierregistro que contenga la cadena foo. Otros tipos de expresiones regulares tepermiten expecificar clases de cadenas ms complicadas.

    Cmo usar Expresiones RegularesUna expresin regular puede ser usada como un patrn encerrandola entre

    barras. Entonces la expresin regular es comparada contra todo el texto de cadaregistro. (Normalmente, solo hace falta que case parte del texto para que elcasamiento tenga xito). Por ejemplo, esto imprime el segundo campo de cadaregistro que contiene foo en cualquier parte del registro:

    awk '/foo/ { print $2 }' ListaBBSLas expresiones regulares pueden tambin ser usadas en expresiones de

    comparacin. Entonces puedes especificar la cadena contra la cual casarla; nonecesita que case el registro de entrada actual completamente. Estas expresiones decomparacin pueden ser usadas como patrones o en sentencias if y while.exp ~ /regexp/

    Esto es cierto si la expresin exp (tomada como una cadena de caracteres) encaja conregexp. Los siguientes ejemplo encajan o seleccionan todos los registros de entradaque contengan la letra J en cualquier posicin dentrl del primer campo:

    awk '$1 ~ /J/' inventarioenviadoO sino:

    awk '{ if ($1 ~ /J/) print }' inventarioenviadoexp !~ /regexp/

    Esto es cierto si la expresin exp (tomada como una cadena de caracteres) noconcuerda con regexp. El siguiente ejemplo encaja o selecciona todos los registros deentrada cuyo primer campo no contiene la letra J en ninguna posicin:

    awk '$1 !~ /J/' inventarioenviado

  • La parte derecha de un operador `~' o `!~' no necesita ser una expresinregular constante (por ejemplo, una cadena de caracteres entre barras). Podra sercualquier expresin. La expresin es evaluada, y convertida si es necesario a unacadena; los contenidos de la cadena sern utilizados como expresin regular. Unaexpresin regular que se comporta de esta forma es llamada expresin regulardinmica. Por ejemplo:identifier_regexp = "[AZaz_][AZaz_09]+"$0 ~ identifier_regexpfija la variable identifier_regexp a una expresin regular que describe nombres devariables de awk, y chequea si el registro de entrada encaja con esta expresinregular.

    Operadores de Expresiones RegularesPuedes combinar expresiones regulares con los siguientes caracteres,

    llamados operadores de expresiones regulares, o metacaracteres, para incrementar elpoder y versatilidad de las expresiones regulares.

    Aqu tienes una tabla de metacaracteres. Todos los caracteres que noaparecen no tienen ningn significado especial en una expresin regular.

    ^

    Esto busca el principio de la cadena o el principio de una lnea dentro de la cadena.Por ejemplo:^@captulo

    coincide con @captulo al principio de una cadena, y puede ser usada paraidentificar comienzos de captulos en ficheros fuentes Texinfo.

    $Esto es similar a ~, pero encaja solo al final de una cadena o el final de una lneadentro de la cadena. Por ejemplo:p$encaja con un registro que acabe en p..

    Esto encaja con cualquier carcter nico, excepto el carcter nueva lnea. Porejemplo:.P

    encaja con cualquier carcter que vaya seguido por una P en una cadena. Usando la

  • concatenacin podemos hacer expresiones regulares como U.A, la cual encaja concualquier secuencia de 3 caracteres que comiencen con una U y acaben con A.

    []Esto recibe el nombre de conjunto de caracteres. Encaja con cualquiera de loscaracteres encerrados entre los corchetes. Por ejemplo:[MVX]encaja con cuales quiera de los caracteres M, V, y X en una cadena.Se pueden especificar rangos de caracteres utilizando un guin entre el carcter deinicio y el carcter final del intervalo de caracteres, y encerrando entre los corchetes.Por ejemplo:[09]encaja con cualquier dgito.Para incluir cualquiera de estos caracteres `\', `]', `' o `^' en un conjunto decaracteres, pon un \ antes del carcter en cuestin. Por ejemplo:[d\]]encaja con ] o d.Este tratamiento de \ es compatible con otras implementaciones de awk peroincompatible con la expecificacin POSIX propuesta para awk. El borrador actualespecifica el uso de la misma sintxis usada en egrep.

    Podramos cambiar gawk para que encajase con el estndar, una vez queestuvisemos seguros de que no volver a cambiar. Mientras tanto, la opcin aespecifica la sintaxis de awk tradicional descrita anteriormente (la cual es tambin lasintaxis por defecto), mientras que la opcin e especifica la sintaxis egrep. (Ver laseccin Opciones de la lnea de comandos).En la sintxis egrep, la barra invertida no tiene sintcticamente significado especialdentro de las llaves. Esto significa que tienen que ser usados trucos especiales pararepresentar los caracteres ], y ^ como miembros de un conjunto de caracteres.Para buscar un coincidencia del carcter , escrbelo como , lo cual es unrango que contiene nicamente el carcter . Podras tambin dar como elprimer o el ltimo carcter del conjunto. Para buscar una coincidencia del carcter^, ponlo en cualquier lugar excepto como el primer carcter de un conjunto. Parabuscar una coincidencia del carcter ], haz que sea el primer carcter del conjunto.Por ejemplo:[]d^]encaja con ], d o ^.

  • [^]Esto es el conjunto de caracteres complementario. El primer carcter despus del [debe ser un ^. Encaja con cuales quiera caracteres excepto aquellos que se metenentre los corchetes. Por ejemplo:[^09]encaja con cualquier carcter que no sea un dgito.Este es el operador alternacin y se usa para especificar alternativas. Por ejemplo:^P[09]encaja con cualquier cadena que encaje con ^P o con [09]. Esto significa queencaja con cualquier cadena que contenga un dgito o comience por P.La alternacin se aplica a la expresin regular posible ms grande a cada lado.

    ()Los parntesis se usan para agrupar expresiones regulares del mismo modo que en lasaritmticas. Pueden ser usados para concatenar expresiones regulares que contenganel operador alternaci&oacuten .*

    Este smbolo significa que la expresin regular precedente se va a repetir tantas vecescomo sea posible para encontrar una concordancia. Por ejemplo:ph*

    aplica el smbolo * a la h precedente y busca la concordancia de una p seguidapor cualquier nmero de haches. Tambin encajar con una nica p que no vayaseguida por ninguna h.

    El * repite la expresin precedente ms pequea posible. (use parntesis si deseasrepetir una expresin ms grande) Encuentra tantas repeticiones como sea posible.Por ejemplo:awk '/\(c[ad][ad]*r x\)/ { print }' sampleimprime cada registro de la entrada que contenga cadenas de la siguiente forma (carx), (cdr x), (cadr x), y as sucesivamente.+

    Este smbolo es similar a *, pero la expresin precedente debe encajar al menos unavez. Esto significa que:

  • wh+y

    encajar con why y whhy pero no con wy, donde sin embaro wh*y encajaracon las tres combinaciones. Esta es una forma ms simple de escribir el ltimoejemplo *:awk '/\(c[ad]+r x\)/ { print }' sample?

    Este smbolo es similar a *, pero la expresin regular precedente puede encajar unavez o ninguna. Por ejemplo:fe?d

    encajar con fed o fd y nada ms.\

    Esto se usa para suprimir el significado especial de un carcter en un matching. Porejemplo:\$busca una coincidencia del carcter $.Las secuencias escape usadas para constantes de cadena (Ver la seccin ExpresionesConstantes) son vlidas en expresiones regulares tambin; ellas son tambinprecedidas por un \.

    En las expresiones regulares, los operadores *, + y ? tienen laprecedencia mayor, seguidos por la concatenacin, y finalmente por . Como en lasaritmticas, los parntesis pueden cambiar el modo en que se agrupen los operadores.

    Sensibilidad a Maysculas en el MatchingLa sensibilidad a maysculas es normalmente significativa en expresiones

    regulares, tambin cuando casa caracteres ordinarios (por ejemplo, no conmetacaracteres), y dentro de conjunto de caracteres. Por lo que una w en unaexpresin regular encaja solamente con una w minscula y nunca con una Wmayscula.

    La forma ms fcil de hace una bsqueda o encaje insensible a maysculases usar el conjunto de caracteres: [Ww]. Sin embargo, esto puede ser embarazoso sinecesitas usarlo a menudo; y puede hacer que la expresin regular sea ms ilegible.Existen otras dos alternativas que podras preferir.

    Una forma de realizar una bsqueda insensible a maysculas en un puntoen particular del programa es convertir el dato a un nico tipo (maysculas ominsculas), usando las funciones empotradas para manejo de cadenas tolower o

  • toupper (que sern explicadas posteriormente en la Seccin Funciones Implcitas(Builtin) para Manipulacin de Cadenas). Por ejemplo:tolower($1) ~ /foo/ { ... }convierte el primer campo a minsculas antes de realizar una bsqueda ocomparacin contra dicho campo.

    Otro mtodo es fijar la variable IGNORECASE a un valor distinto de cero(ver seccin 12. Variables Implcitas (Builtin). Cuando IGNORECASE es distintade cero, todas las operaciones de expresiones regulares son insensibles amaysculas/minsculas. Cambiando el valor de la variable IGNORECASE se puedecontrolar de forma dinmica la sensibilidad a maysculas/minsculas de tu programaen tiempo de ejecucin. La sensibilidad a maysculas/minsculas est activada pordefecto porque la variable IGNORECASE (como la mayora de las variables) esinicializada a cero.

    x = "aB"

    if (x ~ /ab/) ... # esta comprobacin fallarIGNORECASE = 1

    if (x ~ /ab/) ... # esta comprobacin tendr xitoNormalmente no puedes usar IGNORECASE para hacer que ciertas reglas

    sean insensibles a maysculas/minsculas y otras reglas sean sensibles, porque nohay forma de fijar el valor de IGNORECASE solamente para el patrn de una reglaen particular. Para hacer esto, debes usar los conjuntos de caracteres o tolower. Sinembargo, una cosa que puedes hacer solamente con IGNORECASE es activar odesactivar la sensibilidad a maysculas/minsculas para todas las reglas de una vez.

    IGNORECASE puede ser fijado en la lnea de comando, o en una reglaBEGIN. Fijar la variable IGNORECASE en la lnea de comando puede ser una formade hacer a un programa insensible a las maysculas/minsculas sin tener que editarlo.

    El valor de IGNORECASE no tiene ningn efecto si gawk est en modocompatibilidad (Ver la seccin 14. Invocacin de awk). En modo compatibilidad ladiferencia entre maysculas y minsculas es siempre significativa.

    Expresiones de Comparacin comoPatrones Los patrones de comparacin chequean relaciones tales como igualdad entredos cadenas o nmeros. Son un caso especial de patrones de expresiones (ver laSeccin Expresiones como Patrones). Ellos son escritos con operadores relacionales,los cuales son un superconjunto de los mismos en C. Aqu tienes una tabla de ellos:

  • x < y

    Verdad si x es menor que y.

    x y

    Verdad si x es mayor que y.

    x >= y

    Verdad si x es mayor o igual que y.

    x == y

    Verdad si x es igual a y.

    x != y

    Verdad si x no es igual a y.

    x ~ y

    Verdad si x encaja con la expresin regular descrita por y.x !~ y

    Verdad si x no encaja con la expresin regular descrita por y.Los operandos de un operador relacional son comparados como nmeros

    si ambos son nmeros. Si no ellos son convertidos y comparados como cadenas (verla seccin Conversiones de Cadenas y Nmeros). Las cadenas son comparadascomparando el primer carcter de ambas, despus el segundo carcter de ellas y assucesivamente, hasta que encuentre una diferencia. Si las dos cadenas son igualeshasta que se acaba la cadena ms corta, la cadena ms corta se considera menor quela ms larga. Por lo que 10 es menor que 9.

    El operando izquierdo de los operadores ~ y !~ es una cadena. Eloperador derecho es o una expresin regular constante encerrada entre barras(/expreg/), o cualquier expresin, cuyo valor como cadena se usa como una expresinregular dinmica (Ver la seccin Cmo usar Expresiones Regulares)

    El siguiente ejemplo imprime el segundo campo de cada registro deentrada cuyo primer campo valga justamente foo.awk '$1 == "foo" { print $2 }' ListaBBS

    Constrasta esto con el siguiente encaje de expresin regular, el cualaceptara cualquier registro con un primer campo que contuviese la cadena foo.

  • awk '$1 ~ "foo" { print $2 }' ListaBBSo, equivalentemente, este:

    awk '$1 ~ /foo/ { print $2 }' ListaBBS

    Operadores Booleanos como PatronesUn patrn booleano es una expresin la cual combina otros patrones

    usando los operadores booleanos o (), y (&&) y not (!). Donde lospatrones booleanos encajan con un registro de entrada dependiendo de si encajan ono los subpatrones.

    Por ejemplo, el siguiente comando imprime todos los registros en elfichero de entrada ListaBBS que contengan tanto 2400 como foo.

    awk '/2400/ && /foo/' ListaBBS

    El siguiente comando imprime todos los registros en el fichero de entradaListaBBS que contengan 2400 o foo o ambos.

    awk '/2400/ /foo/' ListaBBSEl siguiente comando imprime todos los registros del fichero de entrada

    ListaBBS que no contengan la cadena foo.

    awk '! /foo/' ListaBBS

    Dese cuenta de que los patrones booleanos son un caso especial de lospatrones de expresin (Ver la seccin Expresiones como Patrones); son expresionesque usan los operadores booleanos. Ver la seccin Expresiones Booleanas, para unainformacin completa sobre los operadores booleanos.

    El subpatrn de un patrn booleano pueden ser expresiones regularesconstantes, o cualquier otra expresin gawk. Los patrones de rango no sonexpresiones, por lo que no pueden aparecer dentro de los patrones booleanos. Delmismo modo, los patrones especiales BEGIN y END, los cuales nunca encajan conningn registro de entrada, no son expresiones y no pueden aparecer dentro de lospatrones booleanos.

    Expresiones como PatronesCualquier expresin awk es tambin vlida como un patrn en gawk.

    Entonces el patrn encaja si el valor de la expresin es distinto de cero (si es unnmero) o distinto de nulo (si es una cadena).

    La expresin es evaluada de nuevo cada vez que la regla se chequea contraun nuevo registro de entrada. Si la expresin utiliza campos tales como $1, el valor