stringtranslate.com

AWK

AWK ( / ɔː k / [4] ) es un lenguaje específico de dominio diseñado para el procesamiento de texto y que se utiliza normalmente como herramienta de extracción y generación de informes de datos . Al igual que sed y grep , es un filtro , [4] y es una característica estándar de la mayoría de los sistemas operativos tipo Unix .

El lenguaje AWK es un lenguaje de programación basado en datos que consiste en un conjunto de acciones que se deben realizar contra flujos de datos textuales (ya sea que se ejecuten directamente en archivos o se utilicen como parte de una canalización ) con el fin de extraer o transformar texto, como producir informes formateados. El lenguaje utiliza ampliamente el tipo de datos string , matrices asociativas (es decir, matrices indexadas por cadenas clave) y expresiones regulares . Si bien AWK tiene un dominio de aplicación previsto limitado y fue especialmente diseñado para admitir programas de una sola línea , el lenguaje es Turing-completo , e incluso los primeros usuarios de AWK de Bell Labs a menudo escribían programas AWK grandes y bien estructurados. [5]

AWK fue creado en Bell Labs en la década de 1970, [6] y su nombre se deriva de los apellidos de sus autores: Alfred Aho (autor de egrep ), Peter Weinberger (que trabajó en pequeñas bases de datos relacionales) y Brian Kernighan . El acrónimo se pronuncia igual que el nombre de la especie de ave auk , que se ilustra en la portada de The AWK Programming Language . [7] Cuando se escribe en minúsculas, como awk, se refiere al programa Unix o Plan 9 que ejecuta scripts escritos en el lenguaje de programación AWK.

Historia

Según Brian Kernighan, uno de los objetivos de AWK era tener una herramienta que pudiera manipular fácilmente tanto números como cadenas. AWK también se inspiró en el lenguaje de programación de Marc Rochkind que se usaba para buscar patrones en los datos de entrada y se implementó utilizando yacc . [8]

Como una de las primeras herramientas que aparecieron en la versión 7 de Unix , AWK agregó características computacionales a una tubería de Unix además del shell Bourne , el único lenguaje de scripting disponible en un entorno Unix estándar. Es una de las utilidades obligatorias de la Single UNIX Specification [ 9] y es requerida por la especificación Linux Standard Base [10] .

En 1983, AWK fue una de varias herramientas UNIX disponibles para el sistema operativo UNOS de Charles River Data Systems bajo la licencia de Bell Laboratories . [11]

AWK fue revisado y ampliado significativamente entre 1985 y 1988, lo que dio como resultado la implementación de GNU AWK escrita por Paul Rubin, Jay Fenlason y Richard Stallman , publicada en 1988. [12] GNU AWK puede ser la versión más ampliamente implementada [13] porque está incluida en los paquetes Linux basados ​​en GNU. GNU AWK ha sido mantenido únicamente por Arnold Robbins desde 1994. [12] El código fuente nawk (New AWK) de Brian Kernighan se publicó por primera vez en 1993 sin publicidad, y públicamente desde fines de la década de 1990; muchos sistemas BSD lo usan para evitar la licencia GPL. [12]

AWK fue precedido por sed (1974). Ambos fueron diseñados para el procesamiento de texto. Comparten el paradigma orientado a líneas e impulsado por datos, y son particularmente adecuados para escribir programas de una sola línea , debido al bucle principal implícito y las variables de línea actual. La potencia y la brevedad de los primeros programas AWK (en particular, el potente manejo de expresiones regulares y la concisión debido a las variables implícitas, que facilitan los programas de una sola línea), junto con las limitaciones de AWK en ese momento, fueron inspiraciones importantes para el lenguaje Perl (1987). En la década de 1990, Perl se volvió muy popular, compitiendo con AWK en el nicho de los lenguajes de procesamiento de texto Unix.

Estructura de los programas AWK

AWK lee la entrada línea por línea. Se escanea una línea en busca de cada patrón del programa y, por cada patrón que coincida, se ejecuta la acción asociada.

—  Alfred V. Aho [14]

Un programa AWK es una serie de pares de acciones de patrones, escritos como:

condición  {  acción  } condición  {  acción  } ...

donde la condición es típicamente una expresión y la acción es una serie de comandos. La entrada se divide en registros, donde por defecto los registros están separados por caracteres de nueva línea para que la entrada se divida en líneas. El programa prueba cada registro contra cada una de las condiciones por turno, y ejecuta la acción para cada expresión que sea verdadera. Se puede omitir tanto la condición como la acción. La condición por defecto coincide con cada registro. La acción por defecto es imprimir el registro. Esta es la misma estructura de patrón-acción que sed.

Además de una expresión AWK simple, como foo == 1o /^foo/, la condición puede ser BEGINo ENDque hace que la acción se ejecute antes o después de que se hayan leído todos los registros, o patrón1, patrón2 que coincide con el rango de registros comenzando con un registro que coincide con el patrón1 hasta e incluyendo el registro que coincide con el patrón2 antes de intentar nuevamente coincidir con el patrón1 en líneas subsiguientes.

Además de los operadores aritméticos y lógicos normales, las expresiones AWK incluyen el operador tilde, ~que hace coincidir una expresión regular con una cadena. Como sintaxis útil , /regexp/ sin utilizar el operador tilde hace coincidir con el registro actual; esta sintaxis deriva de sed , que a su vez la heredó del editor ed , donde /se utiliza para realizar búsquedas. Esta sintaxis de utilizar barras como delimitadores para expresiones regulares fue adoptada posteriormente por Perl y ECMAScript , y ahora es común. El operador tilde también fue adoptado por Perl.

Comandos

Los comandos AWK son las instrucciones que se sustituyen por acciones en los ejemplos anteriores. Los comandos AWK pueden incluir llamadas a funciones, asignaciones de variables, cálculos o cualquier combinación de estos. AWK contiene soporte integrado para muchas funciones; muchas más son proporcionadas por las distintas versiones de AWK. Además, algunas versiones admiten la inclusión de bibliotecas vinculadas dinámicamente , que también pueden proporcionar más funciones.

Elimprimirdominio

El comando de impresión se utiliza para generar texto. El texto de salida siempre termina con una cadena predefinida denominada separador de registros de salida (ORS), cuyo valor predeterminado es una nueva línea. La forma más simple de este comando es:

print
Esto muestra el contenido del registro actual. En AWK, los registros se dividen en campos y estos se pueden mostrar por separado:
print $1
Muestra el primer campo del registro actual
print $1, $3
Muestra el primer y tercer campo del registro actual, separados por una cadena predefinida llamada separador de campo de salida (OFS) cuyo valor predeterminado es un solo carácter de espacio.

Aunque estos campos ( $X ) pueden parecerse a variables (el símbolo $ indica variables en los shells habituales de Unix y en Perl ), en realidad se refieren a los campos del registro actual. Un caso especial, $0 , se refiere a todo el registro. De hecho, los comandos " print" y " print $0" son idénticos en funcionalidad.

El comando de impresión también puede mostrar los resultados de cálculos y/o llamadas de funciones:

/regex_pattern/  {  # Acciones a realizar en caso de que el registro (línea) coincida con el patrón regex_pattern anterior  print  3 + 2  print  foobar ( 3 )  print  foobar ( variable )  print  sin ( 3 - 2 ) }

La salida se puede enviar a un archivo:

/regex_pattern/  {  # Acciones a realizar en caso de que el registro (línea) coincida con el patrón regex_pattern anterior  print  "expression"  >  "file name" }

o a través de una tubería :

/regex_pattern/  {  # Acciones a realizar en caso de que el registro (línea) coincida con el patrón regex_pattern anterior  print  "expression"  |  "command" }

Variables incorporadas

Las variables integradas de Awk incluyen las variables de campo: $1, $2, $3, etc. ($0 representa el registro completo). Contienen el texto o los valores de los campos de texto individuales de un registro.

Otras variables incluyen:

Variables y sintaxis

Los nombres de las variables pueden utilizar cualquiera de los caracteres [A-Za-z0-9_], con la excepción de las palabras clave del lenguaje. Los operadores + - * / representan suma, resta, multiplicación y división, respectivamente. Para la concatenación de cadenas , simplemente coloque dos variables (o constantes de cadena) una al lado de la otra. Es opcional utilizar un espacio entre ellas si se trata de constantes de cadena, pero dos nombres de variable colocados uno junto al otro requieren un espacio entre ellos. Las comillas dobles delimitan las constantes de cadena. Las instrucciones no necesitan terminar con punto y coma. Finalmente, se pueden agregar comentarios a los programas utilizando # como el primer carácter de una línea o detrás de un comando o secuencia de comandos.

Funciones definidas por el usuario

En un formato similar al de C , las definiciones de funciones constan de la palabra clave function, el nombre de la función, los nombres de los argumentos y el cuerpo de la función. A continuación, se muestra un ejemplo de una función.

función  add_three  ( número )  {  devolver  número  +  3 }

Esta declaración puede invocarse de la siguiente manera:

( patrón )  {  print  add_three ( 36 )  # Salidas '''39''' }

Las funciones pueden tener variables que se encuentran en el ámbito local. Los nombres de estas se agregan al final de la lista de argumentos, aunque los valores de estas se deben omitir al llamar a la función. Es una convención agregar algunos espacios en blanco en la lista de argumentos antes de las variables locales, para indicar dónde terminan los parámetros y comienzan las variables locales.

Ejemplos

¡Hola Mundo!

Aquí está el programa habitual "¡Hola, mundo!" escrito en AWK:

COMIENZA  {  imprimir  "¡Hola, mundo!"  salir }

Imprimir líneas de más de 80 caracteres

Imprimir todas las líneas de más de 80 caracteres. La acción predeterminada es imprimir la línea actual.

longitud ( $ 0 )  >  80

Contar palabras

Cuente palabras en la entrada e imprima el número de líneas, palabras y caracteres (como wc ):

{  palabras  +=  caracteres NF  += longitud + 1 # agregue uno para tener en cuenta el carácter de nueva línea al final de cada registro (línea) } FIN { imprimir NR , palabras , caracteres }           

Como no hay un patrón para la primera línea del programa, cada línea de entrada coincide de manera predeterminada, por lo que las acciones de incremento se ejecutan para cada línea. words += NFes una abreviatura de words = words + NF.

Suma la última palabra

{  s  +=  $ NF  } FIN  {  imprimir  s  +  0  }

s se incrementa con el valor numérico de $NF , que es la última palabra en la línea según lo definido por el separador de campos de AWK (por defecto, espacio en blanco). NF es el número de campos en la línea actual, p. ej. 4. Dado que $4 es el valor del cuarto campo, $NF es el valor del último campo en la línea independientemente de cuántos campos tenga esta línea, o si tiene más o menos campos que las líneas circundantes. $ es en realidad un operador unario con la precedencia de operador más alta . (Si la línea no tiene campos, entonces NF es 0, $0 es la línea completa, que en este caso está vacía aparte de un posible espacio en blanco, y por lo tanto tiene el valor numérico 0).

Al final de la entrada, el patrón END coincide, por lo que se imprime s . Sin embargo, dado que es posible que no haya habido líneas de entrada en absoluto, en cuyo caso nunca se ha asignado ningún valor a s , por defecto será una cadena vacía. Añadir cero a una variable es un modismo de AWK para convertirla de una cadena a un valor numérico. (Concatenar una cadena vacía es convertirla de un número a una cadena, p. ej. s "" . Tenga en cuenta que no hay ningún operador para concatenar cadenas, solo se colocan adyacentes). Con la coerción, el programa imprime "0" en una entrada vacía, sin ella, se imprime una línea vacía.

Coincidir con un rango de líneas de entrada

NR  %  4  ==  1 ,  NR  %  4  ==  3  {  printf  "%6d %s\n" ,  NR ,  $ 0  }

La instrucción de acción imprime cada línea numerada. La función printf emula la función printf estándar de C y funciona de manera similar al comando print descrito anteriormente. Sin embargo, el patrón para hacer coincidir funciona de la siguiente manera: NR es el número de registros, normalmente líneas de entrada, que AWK ha leído hasta el momento, es decir, el número de línea actual, comenzando en 1 para la primera línea de entrada. % es el operador de módulo . NR % 4 == 1 es verdadero para la 1.ª, 5.ª, 9.ª, etc., líneas de entrada. Del mismo modo, NR % 4 == 3 es verdadero para la 3.ª, 7.ª, 11.ª, etc., líneas de entrada. El patrón de rango es falso hasta que la primera parte coincide, en la línea 1, y luego permanece verdadero hasta que coincide la segunda parte, en la línea 3 inclusive. Luego permanece falso hasta que la primera parte coincide nuevamente en la línea 5.

De esta forma, el programa imprime las líneas 1, 2 y 3, se salta la línea 4, y luego la 5, 6 y 7, y así sucesivamente. Para cada línea, imprime el número de línea (en un campo de 6 caracteres de ancho) y luego el contenido de la línea. Por ejemplo, cuando se ejecuta en esta entrada:

RomaFlorenciaMilánNápolesTurínVenecia

El programa anterior imprime:

 1 Roma 2 Florencia 3 Milán 5 Turín 6 Venecia

Impresión de la parte inicial o final de un archivo

Como caso especial, cuando la primera parte de un patrón de rango es constantemente verdadera, p. ej. 1 , el rango comenzará al principio de la entrada. De manera similar, si la segunda parte es constantemente falsa, p. ej. 0 , el rango continuará hasta el final de la entrada. Por ejemplo,

 /^--cortar aquí--$/ ,  0

imprime líneas de entrada desde la primera línea que coincide con la expresión regular ^--cut here--$ , es decir, una línea que contiene solo la frase "--cut here--", hasta el final.

Calcular frecuencias de palabras

Frecuencia de palabras utilizando matrices asociativas :

BEGIN  {  FS = "[^a-zA-Z]+" } {  para  ( i = 1 ;  i <= NF ;  i ++ )  palabras [ tolower ( $ i )] ++ } END  {  para  ( i  en  palabras )  imprimir  i ,  palabras [ i ] }

El bloque BEGIN establece el separador de campo en cualquier secuencia de caracteres no alfabéticos. Los separadores pueden ser expresiones regulares. Después de eso, llegamos a una acción simple, que realiza la acción en cada línea de entrada. En este caso, para cada campo de la línea, sumamos uno al número de veces que aparece esa palabra, primero convertida a minúsculas. Finalmente, en el bloque END, imprimimos las palabras con sus frecuencias. La línea

para (yo en palabras)

crea un bucle que recorre la matriz words y asigna i a cada subíndice de la matriz. Esto es diferente de la mayoría de los lenguajes, donde un bucle de este tipo recorre cada valor de la matriz. El bucle imprime así cada palabra seguida de su recuento de frecuencia. tolowerfue una adición al One True awk (ver más abajo) realizada después de la publicación del libro.

Coincidir con patrones desde la línea de comandos

Este programa se puede representar de varias maneras. La primera utiliza el shell Bourne para crear un script de shell que lo hace todo. Es el más corto de estos métodos:

#!/bin/shpatrón = " $1 " shift
awk '/' " $patrón " '/ { print NOMBRE_ARCHIVO ": " $0 }' " $@ "  

El $patterncomando awk no está protegido por comillas simples, por lo que el shell expande la variable, pero debe colocarse entre comillas dobles para manejar correctamente los patrones que contienen espacios. Un patrón por sí solo, de la manera habitual, verifica si la línea completa ( $0) coincide. FILENAMEcontiene el nombre de archivo actual. awk no tiene un operador de concatenación explícito; dos cadenas adyacentes las concatenan. $0se expande a la línea de entrada original sin cambios.

Existen otras formas de escribir esto. Este script de shell accede al entorno directamente desde awk:

#!/bin/shexportar patrón = " $1 " shift
awk '$0 ~ ENVIRON["patrón"] { imprimir NOMBRE_ARCHIVO ": " $0 }' " $@ "   

Este es un script de shell que utiliza ENVIRON, una matriz introducida en una versión más reciente de One True awk después de que se publicó el libro. El subíndice de ENVIRONes el nombre de una variable de entorno; su resultado es el valor de la variable. Esto es como la función getenv en varias bibliotecas estándar y POSIX . El script de shell crea una variable de entorno patternque contiene el primer argumento, luego descarta ese argumento y hace que awk busque el patrón en cada archivo.

~Comprueba si su operando izquierdo coincide con su operando derecho; !~es su inverso. Una expresión regular es simplemente una cadena y se puede almacenar en variables.

El siguiente método utiliza la asignación de variables mediante la línea de comandos, en la que un argumento de awk puede verse como una asignación a una variable:

#!/bin/shpatrón = " $1 " shift
awk '$0 ~ patrón { print NOMBRE_ARCHIVO ": $0 }' "patrón= $patrón " " $@ "   

O puede utilizar la opción de línea de comando -v var=value (por ejemplo awk -v pattern="$pattern" ... ).

Finalmente, esto está escrito en awk puro, sin ayuda de un shell o sin la necesidad de saber demasiado sobre la implementación del script awk (como lo hace la asignación de variables en la línea de comandos), pero es un poco largo:

BEGIN  {  patrón  =  ARGV [ 1 ]  para  ( i  =  1 ;  i  <  ARGC ;  i ++ )  # eliminar el primer argumento  ARGV [ i ]  =  ARGV [ i  +  1 ]  ARGC --  si  ( ARGC  ==  1 )  {  # el patrón era lo único, por lo que se fuerza la lectura desde la entrada estándar (usada por el libro)  ARGC  =  2  ARGV [ 1 ]  =  "-"  } } $ 0  ~  patrón  {  imprimir  NOMBRE_ARCHIVO  ":  $ 0  }

Es BEGINnecesario no solo extraer el primer argumento, sino también evitar que se interprete como un nombre de archivo una vez que BEGINfinaliza el bloque. ARGC, el número de argumentos, siempre se garantiza que sea ≥1, al igual que ARGV[0]el nombre del comando que ejecutó el script, con mayor frecuencia la cadena "awk". ARGV[ARGC]es la cadena vacía, "". #inicia un comentario que se expande hasta el final de la línea.

Tenga en cuenta que el ifbloque awk solo verifica si debe leer desde la entrada estándar antes de ejecutar el comando. Esto significa que

awk 'prog'

¡Solo funciona porque el hecho de que no haya nombres de archivos se comprueba antes de progejecutarse! Si lo configura explícitamente ARGCen 1 para que no haya argumentos, awk simplemente se cerrará porque considera que no hay más archivos de entrada. Por lo tanto, debe indicar explícitamente que se lea desde la entrada estándar con el nombre de archivo especial -.

Scripts AWK autónomos

En sistemas operativos tipo Unix se pueden construir scripts AWK autónomos utilizando la sintaxis shebang .

Por ejemplo, un script que envía el contenido de un archivo determinado a la salida estándar se puede crear creando un archivo print.awkcon el siguiente contenido:

#!/usr/bin/awk -f {  imprimir  $ 0  }

Se puede invocar con:./print.awk <filename>

Le -fdice a awk que el argumento que sigue es el archivo desde el que se leerá el programa AWK, que es el mismo indicador que se utiliza en sed. Dado que se utilizan a menudo para líneas de comandos, ambos programas ejecutan de forma predeterminada un programa dado como argumento de línea de comandos, en lugar de un archivo independiente.

Versiones e implementaciones

AWK se escribió originalmente en 1977 y se distribuyó con la versión 7 de Unix .

En 1985 sus autores comenzaron a expandir el lenguaje, principalmente agregando funciones definidas por el usuario. El lenguaje se describe en el libro The AWK Programming Language , publicado en 1988, y su implementación se puso a disposición en versiones de UNIX System V. Para evitar confusiones con la versión anterior incompatible, a esta versión a veces se la llamó "new awk" o nawk . Esta implementación se lanzó bajo una licencia de software libre en 1996 y aún es mantenida por Brian Kernighan (ver enlaces externos a continuación). [ cita requerida ]

Las versiones antiguas de Unix, como UNIX/32V , incluían awkcc, que convertía AWK a C. Kernighan escribió un programa para convertir awk a C++; se desconoce su estado. [16]

El manual de gawk tiene una lista de más implementaciones de Awk. [24]

Libros

Véase también

Referencias

  1. ^ Stutz, Michael (19 de septiembre de 2006). "Comience a usar GAWK: fundamentos del lenguaje AWK" (PDF) . developerWorks . IBM . Archivado (PDF) del original el 27 de abril de 2015 . Consultado el 29 de enero de 2015 . [AWK] se denomina a menudo un lenguaje basado en datos: las instrucciones del programa describen los datos de entrada que se deben comparar y procesar en lugar de una secuencia de pasos del programa
  2. ^ Andreas J. Pilavakis (1989). Taller sobre UNIX . Macmillan International Higher Education. pág. 196.
  3. ^ Arnold Robbins (2015). Programación Awk eficaz: procesamiento de texto universal y coincidencia de patrones (4.ª ed.). O'Reilly Media. pág. 560.
  4. ^ ab James W. Livingston (2 de mayo de 1988). "El gran programa awk no es un tonto". Digital Review . p. 91.
  5. ^ Raymond, Eric S. "Aplicación de minilenguajes". El arte de la programación en Unix . Caso práctico: awk. Archivado desde el original el 30 de julio de 2008. Consultado el 11 de mayo de 2010. El lenguaje de acción awk es Turing-completo y puede leer y escribir archivos.
  6. ^ Aho, Alfred V. ; Kernighan, Brian W. ; Weinberger, Peter J. (1 de septiembre de 1978). Awk — A Pattern Scanning and Processing Language (Segunda edición) (Informe técnico). Manual de Unix, séptima edición, volumen 2. Bell Telephone Laboratories, Inc. . Consultado el 1 de febrero de 2020 .
  7. ^ ab Aho, Alfred V.; Kernighan, Brian W.; Weinberger, Peter J. (1988). El lenguaje de programación AWK. Addison-Wesley Publishing Company. ISBN 9780201079814. Recuperado el 16 de mayo de 2015 .
  8. ^ "Especial UNIX: profesores Kernighan y Brailsford". Computerphile . 30 de septiembre de 2015. Archivado desde el original el 22 de noviembre de 2021.
  9. ^ "Tabla de interfaz de utilidades de la especificación única UNIX, versión 3". Archivado desde el original el 5 de enero de 2018. Consultado el 18 de diciembre de 2005 .
  10. ^ "Capítulo 15. Comandos y utilidades". Linux Standard Base Core Specification 4.0 (informe técnico). Linux Foundation. 2008. Archivado desde el original el 16 de octubre de 2019. Consultado el 1 de febrero de 2020 .
  11. ^ La guía privilegiada del universo (PDF) . Charles River Data Systems, Inc. 1983. pág. 13.
  12. ^ abc Robbins, Arnold (marzo de 2014). "El Proyecto GNU y yo: 27 años con GNU AWK" (PDF) . skeeve.com . Archivado (PDF) del original el 6 de octubre de 2014 . Consultado el 4 de octubre de 2014 .
  13. ^ Dougherty, Dale; Robbins, Arnold (1997). sed y awk (2ª ed.). Sebastopol, CA: O'Reilly. pag. 221.ISBN 1-565-92225-5.
  14. ^ Hamilton, Naomi (30 de mayo de 2008). "The AZ of Programming Languages: AWK". Computerworld . Archivado desde el original el 2020-02-01 . Consultado el 2008-12-12 .
  15. ^ ab "Registros (Guía del usuario de GNU Awk)". Archivado desde el original el 14 de junio de 2020. Consultado el 23 de mayo de 2020 .
  16. ^ Kernighan, Brian W. (24-25 de abril de 1991). Un traductor de AWK a C++ (PDF) . Conferencia Usenix C++. Washington, DC. págs. 217-228. Archivado (PDF) desde el original el 22 de junio de 2020 . Consultado el 1 de febrero de 2020 .
  17. ^ "Registro de trabajo de FreeBSD para importar BWK awk al núcleo de FreeBSD". 16 de mayo de 2005. Archivado desde el original el 8 de septiembre de 2013. Consultado el 20 de septiembre de 2006 .
  18. ^ "Procesamiento de CSV con gawk (utilizando la extensión gawk-csv)". gawkextlib . 2018. Archivado desde el original el 25 de marzo de 2020.
  19. ^ James K. Lawless (1 de mayo de 1997). "Examinando el compilador TAWK". Diario del Dr. Dobb . Archivado desde el original el 21 de febrero de 2020. Consultado el 21 de febrero de 2020 .
  20. ^ "Jawk en SourceForge". Archivado desde el original el 27 de mayo de 2007. Consultado el 23 de agosto de 2006 .
  21. ^ "Página de inicio de xgawk". Archivado desde el original el 18 de abril de 2013. Consultado el 7 de mayo de 2013 .
  22. ^ "QSEAWK en GitHub". GitHub . Archivado desde el original el 2018-06-11 . Consultado el 2017-09-06 .
  23. ^ "CLAWK en GitHub". GitHub . Archivado desde el original el 2021-08-25 . Consultado el 2021-06-01 .
  24. ^ "B.5 Otras implementaciones de awk disponibles libremente". GAWK: Programación AWK efectiva: Guía del usuario para GNU Awk .

Lectura adicional

Enlaces externos