Awk es un lenguaje de secuencias de comandos de propósito general diseñado para el procesamiento de texto avanzado. Se utiliza principalmente como una herramienta de informes y análisis.

A diferencia de la mayoría de los otros lenguajes de programación que son de procedimiento, awk está basado en datos, lo que significa que usted define un conjunto de acciones que se realizarán en el texto de entrada. Toma los datos de entrada, los transforma y envía el resultado a la salida estándar.

Este artículo cubre los aspectos esenciales del lenguaje de programación awk. Conocer los conceptos básicos de awk mejorará significativamente su capacidad para manipular archivos de texto en la línea de comandos.

Cómo awkfunciona

Hay varias implementaciones diferentes de awk. Usaremos la implementación GNU de awk, que se llama gawk. En la mayoría de los sistemas Linux, el awkintérprete es solo un enlace simbólico a gawk.

registros y campos

Awk puede procesar archivos y flujos de datos textuales. Los datos de entrada se dividen en registros y campos. Awk opera en un registro a la vez hasta que se alcanza el final de la entrada. Los registros están separados por un carácter llamado separador de registros. El separador de registros predeterminado es el carácter de nueva línea, lo que significa que cada línea en los datos de texto es un registro. Se puede establecer un nuevo separador de registros usando la RSvariable.

Los registros consisten en campos que están separados por el separador de campo. De forma predeterminada, los campos están separados por un espacio en blanco, incluidos uno o más caracteres de tabulación, espacio y nueva línea.

Los campos de cada registro se referencian con el signo de dólar ( $) seguido del número de campo, comenzando con 1. El primer campo se representa con $1, el segundo con $2, y así sucesivamente. El último campo también se puede referenciar con la variable especial $NFSe puede hacer referencia a todo el registro con $0.

Aquí hay una representación visual que muestra cómo hacer referencia a registros y campos:

tmpfs      788M  1.8M  786M   1% /run/lock 
/dev/sda1  234G  191G   31G  87% /
|-------|  |--|  |--|   |--| |-| |--------| 
   $1       $2    $3     $4   $5  $6 ($NF) --> fields
|-----------------------------------------| 
                    $0                     --> record

programa awk

Para procesar un texto con awk, escribe un programa que le dice al comando qué hacer. El programa consta de una serie de reglas y funciones definidas por el usuario. Cada regla contiene un patrón y un par de acciones. Las reglas están separadas por nueva línea o punto y coma ( ;). Por lo general, un programa awk se ve así:

pattern { action }
pattern { action }
...

Cuando awkprocesa datos, si el patrón coincide con el registro, realiza la acción especificada en ese registro. Cuando la regla no tiene patrón, todos los registros (líneas) coinciden.

Una acción awk está encerrada entre llaves ( {}) y consta de declaraciones. Cada instrucción especifica la operación a realizar. Una acción puede tener más de una declaración separada por nueva línea o punto y coma ( ;). Si la regla no tiene acción, por defecto imprime todo el registro.

Awk admite diferentes tipos de declaraciones, incluidas expresiones, condicionales, declaraciones de entrada, salida y más. Las declaraciones awk más comunes son:

  • exit- Detiene la ejecución de todo el programa y sale.
  • next- Detiene el procesamiento del registro actual y pasa al siguiente registro en los datos de entrada.
  • print- Imprimir registros, campos, variables y texto personalizado.
  • printf- Le da más control sobre el formato de salida, similar a C y bash printf .

Al escribir programas awk, todo lo que sigue a la marca hash (#)y hasta el final de la línea se considera un comentario. Las líneas largas se pueden dividir en varias líneas usando el carácter de continuación, barra invertida ( \).

Ejecutando programas awk

Un programa awk se puede ejecutar de varias maneras. Si el programa es corto y simple, se puede pasar directamente al awkintérprete en la línea de comandos:

awk 'program' input-file...

Al ejecutar el programa en la línea de comandos, debe estar entre comillas simples ( ''), para que el shell no interprete el programa.

Si el programa es grande y complejo, lo mejor es ponerlo en un archivo y usar la -fopción de pasar el archivo al awkcomando:

awk -f program-file input-file...

En los ejemplos a continuación, usaremos un archivo llamado "teams.txt" que se parece al siguiente:

Bucks Milwaukee    60 22 0.732 
Raptors Toronto    58 24 0.707 
76ers Philadelphia 51 31 0.622
Celtics Boston     49 33 0.598
Pacers Indiana     48 34 0.585

Patrones extraños

Los patrones en awk controlan si la acción asociada debe ejecutarse o no.

Awk admite diferentes tipos de patrones, incluidos patrones de expresión regular, expresión de relación, rango y expresión especial.

Cuando la regla no tiene patrón, cada registro de entrada coincide. Aquí hay un ejemplo de una regla que contiene solo una acción:

awk '{ print $3 }' teams.txt

El programa imprimirá el tercer campo de cada registro:

60
58
51
49
48

Patrones de expresiones regulares

Una expresión regular o regex es un patrón que coincide con un conjunto de cadenas. Los patrones de expresiones regulares de Awk están encerrados entre barras ( //):

/regex pattern/ { action }

El ejemplo más básico es una coincidencia de cadena o carácter literal. Por ejemplo, para mostrar el primer campo de cada registro que contiene "0.5", ejecutaría el siguiente comando:

awk '/0.5/ { print $1 }' teams.txt
Celtics
Pacers

El patrón puede ser cualquier tipo de expresión regular extendida. Aquí hay un ejemplo que imprime el primer campo si el registro comienza con dos o más dígitos:

awk '/^[0-9][0-9]/ { print $1 }' teams.txt
76ers

Patrones de expresiones relacionales

Los patrones de expresiones relacionales se utilizan generalmente para hacer coincidir el contenido de un campo o variable específicos.

De forma predeterminada, los patrones de expresiones regulares se comparan con los registros. Para hacer coincidir una expresión regular con un campo, especifique el campo y use el operador de comparación "contener" ( ~) con el patrón.

Por ejemplo, para imprimir el primer campo de cada registro cuyo segundo campo contenga “ia”, escribiría:

awk '$2 ~ /ia/ { print $1 }' teams.txt
76ers
Pacers

Para hacer coincidir campos que no contienen un patrón dado, use el !~operador:

awk '$2 !~ /ia/ { print $1 }' teams.txt
Bucks
Raptors
Celtics

Puede comparar cadenas o números para relaciones como mayor que, menor que, igual, etc. El siguiente comando imprime el primer campo de todos los registros cuyo tercer campo es mayor que 50:

awk '$3 > 50 { print $1 }' teams.txt
Bucks
Raptors
76ers

Patrones de rango

Los patrones de rango constan de dos patrones separados por una coma:

pattern1, pattern2

Todos los registros que comienzan con un registro que coincide con el primer patrón hasta que coinciden con un registro que coincide con el segundo patrón.

Aquí hay un ejemplo que imprimirá el primer campo de todos los registros a partir del registro que incluye "Raptors" hasta el registro que incluye "Celtics":

awk '/Raptors/,/Celtics/ { print $1 }' teams.txt
Raptors
76ers
Celtics

Los patrones también pueden ser expresiones de relación. El siguiente comando imprimirá todos los registros a partir de aquel cuyo cuarto campo es igual a 32 hasta aquel cuyo cuarto campo es igual a 33:

awk '$4 == 31, $4 == 33 { print $0 }' teams.txt
76ers Philadelphia 51 31 0.622
Celtics Boston     49 33 0.598

Los patrones de rango no se pueden combinar con otras expresiones de patrón.

Patrones de expresiones especiales

Awk incluye los siguientes patrones especiales:

  • BEGIN- Se utiliza para realizar acciones antes de que se procesen los registros.
  • END- Se utiliza para realizar acciones después de que se procesan los registros.

El BEGINpatrón generalmente se usa para establecer variables y el ENDpatrón para procesar datos de los registros, como el cálculo.

El siguiente ejemplo imprimirá "Iniciar procesamiento", luego imprimirá el tercer campo de cada registro y finalmente "Terminar procesamiento":

awk 'BEGIN { print "Start Processing." }; { print $3 }; END { print "End Processing." }' teams.txt
Start Processing
60
58
51
49
48
End Processing.

Si un programa tiene solo un BEGINpatrón, las acciones se ejecutan y la entrada no se procesa. Si un programa solo tiene un ENDpatrón, la entrada se procesa antes de realizar las acciones de la regla.

La versión Gnu de awk también incluye dos patrones especiales más BEGINFILEENDFILE, que le permite realizar acciones al procesar archivos.

Combinando patrones

Awk le permite combinar dos o más patrones utilizando el operador lógico AND ( &&) y el operador lógico OR ( ||).

Aquí hay un ejemplo que usa el &&operador para imprimir el primer campo de aquellos registros cuyo tercer campo es mayor a 50 y el cuarto campo es menor a 30:

awk '$3 > 50 && $4 < 30 { print $1 }' teams.txt
Bucks
Raptors

Variables integradas

Awk tiene una serie de variables integradas que contienen información útil y le permite controlar cómo se procesa el programa. A continuación se muestran algunas de las variables integradas más comunes:

  • NF- El número de campos en el registro.
  • NR- El número del registro actual.
  • FILENAME- El nombre del archivo de entrada que se procesa actualmente.
  • FS- Separador de campos.
  • RS- Separador de registros.
  • OFS- Separador de campo de salida.
  • ORS- Separador de registros de salida.

Aquí hay un ejemplo que muestra cómo imprimir el nombre del archivo y el número de líneas (registros):

awk 'END { print "File", FILENAME, "contains", NR, "lines." }' teams.txt
File teams.txt contains 5 lines.

Las variables en AWK se pueden configurar en cualquier línea del programa. Para definir una variable para todo el programa, colóquela en un BEGINpatrón.

Cambio del separador de campos y registros

El valor predeterminado del separador de campo es cualquier número de espacios o caracteres de tabulación. Se puede cambiar configurando en la FSvariable.

Por ejemplo, para establecer el separador de campo ., usaría:

awk 'BEGIN { FS = "." } { print $1 }' teams.txt
Bucks Milwaukee    60 22 0
Raptors Toronto    58 24 0
76ers Philadelphia 51 31 0
Celtics Boston     49 33 0
Pacers Indiana     48 34 0

El separador de campo también se puede establecer en más de un carácter:

awk 'BEGIN { FS = ".." } { print $1 }' teams.txt

Al ejecutar awk one-liners en la línea de comandos, también puede usar la -Fopción para cambiar el separador de campo:

awk -F "." '{ print $1 }' teams.txt

De forma predeterminada, el separador de registros es un carácter de nueva línea y se puede cambiar mediante la RSvariable.

Aquí hay un ejemplo que muestra cómo cambiar el separador de registro a .:

awk 'BEGIN { RS = "." } { print $1 }' teams.txt
Bucks Milwaukee    60 22 0
732 
Raptors Toronto    58 24 0
707 
76ers Philadelphia 51 31 0
622
Celtics Boston     49 33 0
598
Pacers Indiana     48 34 0
585

Acciones Awk

Las acciones de Awk se encierran entre llaves ( {}) y se ejecutan cuando el patrón coincide. Una acción puede tener cero o más declaraciones. Las declaraciones múltiples se ejecutan en el orden en que aparecen y deben estar separadas por nueva línea o punto y coma ( ;).

Hay varios tipos de instrucciones de acción compatibles con awk:

  • Expresiones, como asignación de variables, operadores aritméticos, operadores de incremento y decremento.
  • Sentencias de control, utilizadas para controlar el flujo del programa ( ifforwhileswitchy más)
  • Instrucciones de salida, como printprintf.
  • Sentencias compuestas, para agrupar otras sentencias.
  • Declaraciones de entrada, para controlar el procesamiento de la entrada.
  • Instrucciones de eliminación, para eliminar elementos de la matriz.

La printdeclaración es probablemente la declaración awk más utilizada. Imprime una salida formateada de texto, registros, campos y variables.

Al imprimir varios elementos, debe separarlos con comas. Aquí hay un ejemplo:

awk '{ print $1, $3, $5 }' teams.txt

Los elementos impresos están separados por espacios simples:

Bucks 60 0.732
Raptors 58 0.707
76ers 51 0.622
Celtics 49 0.598
Pacers 48 0.585

Si no usa comas, no habrá espacio entre los elementos:

awk '{ print $1 $3 $5 }' teams.txt

Los elementos impresos se concatenan:

Bucks600.732
Raptors580.707
76ers510.622
Celtics490.598
Pacers480.585

Cuando printse usa sin un argumento, el valor predeterminado es print $0Se imprime el registro actual.

Para imprimir un texto personalizado, debe citar el texto con caracteres de comillas dobles:

awk '{ print "The first field:", $1}' teams.txt
The first field: Bucks
The first field: Raptors
The first field: 76ers
The first field: Celtics
The first field: Pacers

También puede imprimir caracteres especiales como nueva línea:

awk 'BEGIN { print "First line\nSecond line\nThird line" }'
First line
Second line
Third line

La printfdeclaración le da más control sobre el formato de salida. Aquí hay un ejemplo que inserta números de línea:

awk '{ printf "%3d. %s\n", NR, $0 }' teams.txt

printfno crea una nueva línea después de cada registro, por lo que estamos usando \n:

  1. Bucks Milwaukee    60 22 0.732 
  2. Raptors Toronto    58 24 0.707 
  3. 76ers Philadelphia 51 31 0.622
  4. Celtics Boston     49 33 0.598
  5. Pacers Indiana     48 34 0.585

El siguiente comando calcula la suma de los valores almacenados en el tercer campo de cada línea:

awk '{ sum += $3 } END { printf "%d\n", sum }' teams.txt
266

Aquí hay otro ejemplo que muestra cómo usar expresiones y declaraciones de control para imprimir los cuadrados de los números del 1 al 5:

awk 'BEGIN { i = 1; while (i < 6) { print "Square of", i, "is", i*i; ++i } }'
Square of 1 is 1
Square of 2 is 4
Square of 3 is 9
Square of 4 is 16
Square of 5 is 25

Los comandos de una línea como el anterior son más difíciles de entender y mantener. Al escribir programas más largos, debe crear un archivo de programa separado:

prg.awk
BEGIN { 
  i = 1
  while (i < 6) { 
    print "Square of", i, "is", i*i; 
    ++i 
  } 
}

Ejecute el programa pasando el nombre del archivo al awkintérprete:

awk -f prg.awk

También puede ejecutar un programa awk como ejecutable utilizando la directiva shebangawk y configurando el intérprete:

prg.awk
#!/usr/bin/awk -f
BEGIN { 
  i = 1
  while (i < 6) { 
    print "Square of", i, "is", i*i; 
    ++i 
  } 
}

Guarde el archivo y hágalo ejecutable :

chmod +x prg.awk

Ahora puede ejecutar el programa ingresando:

./prg.awk

Uso de variables de shell en programas Awk

Si está utilizando el awkcomando en scripts de shell, lo más probable es que necesite pasar una variable de shell al programa awk. Una opción es encerrar el programa con comillas dobles en lugar de simples y sustituir la variable en el programa. Sin embargo, esta opción hará que su programa awk sea más complejo ya que necesitará escapar de las variables awk.

La forma recomendada de usar variables de shell en programas awk es asignar la variable de shell a una variable awk. Aquí hay un ejemplo:

num=51awk -v n="$num" 'BEGIN {print n}'
51

Conclusión

Awk es una de las herramientas más poderosas para la manipulación de texto.

Este artículo apenas toca la superficie del lenguaje de programación awk. Para obtener más información sobre awk, consulte la documentación oficial de Gawk .

Si tiene alguna pregunta o comentario, no dude en dejar un comentario.