Cómo usar el comando awk en Linux

Una computadora portátil Linux con líneas de código en una ventana de terminal.
Fatmawati Achmad Zaenuri / Shutterstock

En Linux,  awkes un dínamo de manipulación de texto de línea de comandos, así como un poderoso lenguaje de programación. Aquí hay una introducción a algunas de sus características más interesantes.

Cómo awk obtuvo su nombre

El  awk comando fue nombrado usando las iniciales de las tres personas que escribieron la versión original en 1977:  Alfred Aho , Peter Weinberger y Brian Kernighan . Estos tres hombres eran del legendario  panteón Unix de AT&T Bell Laboratories . Con las contribuciones de muchos otros desde entonces, awk ha seguido evolucionando.

Es un lenguaje de programación completo, así como un conjunto de herramientas de manipulación de texto completo para la línea de comandos. Si este artículo abre el apetito, puede revisar todos los detalles acerca  awk y su funcionalidad.

Reglas, patrones y acciones

awktrabaja en programas que contienen reglas compuestas por patrones y acciones. La acción se ejecuta en el texto que coincide con el patrón. Los patrones se encierran entre llaves ( {}). Juntos, un patrón y una acción forman una regla. El awkprograma completo está entre comillas simples ( ').

Echemos un vistazo al tipo de awkprograma más simple . No tiene patrón, por lo que coincide con todas las líneas de texto introducidas en él. Esto significa que la acción se ejecuta en cada línea. Vamos a usarlo en la salida de la whoorden.

Aquí está la salida estándar de who:

OMS

El comando "quién" en una ventana de terminal.

Quizás no necesitemos toda esa información, sino más bien, solo queremos ver los nombres en las cuentas. Podemos canalizar la salida desde whodentro awky luego decirle awkque imprima solo el primer campo.

De forma predeterminada, awkconsidera que un campo es una cadena de caracteres rodeada por espacios en blanco, el comienzo de una línea o el final de una línea. Los campos se identifican con un signo de dólar ( $) y un número. Entonces,  $1representa el primer campo, que usaremos con la print acción para imprimir el primer campo.

Escribimos lo siguiente:

quien | awk '{imprimir $ 1}'

El comando "who | awk '{print $ 1}'" en una ventana de terminal.

awk imprime el primer campo y descarta el resto de la línea.

Podemos imprimir tantos campos como queramos. Si agregamos una coma como separador,  awkimprime un espacio entre cada campo.

Escribimos lo siguiente para imprimir también la hora en que la persona inició sesión (campo cuatro):

quien | awk '{imprimir $ 1, $ 4}'

El comando "who | awk '{print $ 1, $ 4}'" en una ventana de terminal.

Hay un par de identificadores de campo especiales. Estos representan la línea completa de texto y el último campo en la línea de texto:

  • $ 0 : representa la línea completa de texto.
  • $ 1 : representa el primer campo.
  • $ 2 : representa el segundo campo.
  • $ 7 : representa el séptimo campo.
  • $ 45 : representa el campo 45.
  • $ NF : Significa «número de campos» y representa el último campo.

Escribiremos lo siguiente para que aparezca un pequeño archivo de texto que contiene una breve cita atribuida a Dennis Ritchie :

gato dennis_ritchie.txt

El comando "cat dennis_ritchie.txt" en una ventana de terminal.

Queremos  awkimprimir el primer, segundo y último campo de la cotización. Tenga en cuenta que, aunque está envuelto en la ventana de la terminal, es solo una línea de texto.

Relacionado:  Cómo usar el comando whois en Linux

Escribimos el siguiente comando:

awk '{imprimir $ 1, $ 2, $ NF}' dennis_ritchie.txt

El comando "awk '{print $ 1, $ 2, $ NF}' dennis_ritchie.txt" en una ventana de terminal.

No conocemos esa «simplicidad». es el campo número 18 en la línea de texto, y no nos importa. Lo que sí sabemos es que es el último campo y podemos usarlo $NFpara obtener su valor. El período se considera simplemente otro carácter en el cuerpo del campo.

Agregar separadores de campo de salida

También puede indicarle awkque imprima un carácter particular entre campos en lugar del carácter de espacio predeterminado. La salida predeterminada del  date comando es un poco peculiar  porque el tiempo se coloca justo en el medio. Sin embargo, podemos escribir lo siguiente y usarlo awkpara extraer los campos que queramos:

fecha
fecha | awk '{imprimir $ 2, $ 3, $ 6}'

El comando "date" y "date | awk '{print $ 2, $ 3, $ 6}'" en una ventana de terminal.

Usaremos la OFS variable (separador de campo de salida) para poner un separador entre el mes, el día y el año. Tenga en cuenta que a continuación incluimos el comando entre comillas simples ( '), no entre llaves ( {}):

fecha | awk 'OFS = "/" {imprimir $ 2, $ 3, $ 6}'
fecha | awk 'OFS = "-" {imprimir $ 2, $ 3, $ 6}'

Los comandos "date | awk 'OFS =" / "{print $ 2, $ 3, $ 6}'" y "date | awk 'OFS =" - "{print $ 2, $ 3, $ 6}'" en una ventana de terminal.

Las reglas BEGIN y END

Una BEGINregla se ejecuta una vez antes de que comience el procesamiento de texto. De hecho, se ejecuta awk incluso antes de leer cualquier texto. Una ENDregla se ejecuta después de que se haya completado todo el procesamiento. Puede tener múltiples reglas BEGIN y  END, y se ejecutarán en orden.

Para nuestro ejemplo de una BEGINregla, imprimiremos la cita completa del dennis_ritchie.txtarchivo que usamos anteriormente con un título encima.

Para hacerlo, escribimos este comando:

awk 'BEGIN {print "Dennis Ritchie"} {print $ 0}' dennis_ritchie.txt

El comando "awk 'BEGIN {print" Dennis Ritchie "} {print $ 0}' dennis_ritchie.txt" en una ventana de terminal.

Tenga en cuenta que la BEGINregla tiene su propio conjunto de acciones encerradas dentro de su propio conjunto de llaves ( {}).

Podemos usar esta misma técnica con el comando que usamos anteriormente para canalizar la salida desde whoadentro awk. Para hacerlo, escribimos lo siguiente:

quien | awk 'BEGIN {print "Active Sessions"} {print $ 1, $ 4}'

El comando "who | awk 'BEGIN {print" Active Sessions "} {print $ 1, $ 4}'" en una ventana de terminal.

Separadores de campo de entrada

Si desea awktrabajar con texto que no usa espacios en blanco para separar campos, debe indicarle qué carácter usa el texto como separador de campo. Por ejemplo, el /etc/passwdarchivo usa dos puntos ( :) para separar campos.

Usaremos ese archivo y la -Fopción (cadena de separación) para indicarle awkque use los dos puntos ( :) como separador. Escribimos lo siguiente para decirle awk que imprima el nombre de la cuenta de usuario y la carpeta de inicio:

awk -F: '{imprimir $ 1, $ 6}' / etc / passwd

El comando "awk -F: '{print $ 1, $ 6}' / etc / passwd" en una ventana de terminal.

La salida contiene el nombre de la cuenta de usuario (o el nombre de la aplicación o demonio) y la carpeta de inicio (o la ubicación de la aplicación).

Salida del comando "awk -F: '{print $ 1, $ 6}' / etc / passwd" en una ventana de terminal.

Adición de patrones

Si lo único que nos interesa son las cuentas de usuario habituales, podemos incluir un patrón con nuestra acción de impresión para filtrar todas las demás entradas. Debido a que los  números de identificación de usuario son iguales o mayores que 1,000, podemos basar nuestro filtro en esa información.

Relacionado:  Cómo usar el comando ar de Linux para crear bibliotecas estáticas

Escribimos lo siguiente para ejecutar nuestra acción de impresión solo cuando el tercer campo ( $3) contiene un valor de 1,000 o mayor:

awk -F: '$ 3> = 1000 {imprimir $ 1, $ 6}' / etc / passwd

El comando "awk -F: '$ 3> = 1000 {print $ 1, $ 6}' / etc / passwd" en una ventana de terminal.

El patrón debe preceder inmediatamente a la acción con la que está asociado.

Podemos usar la BEGINregla para proporcionar un título a nuestro pequeño informe. Escribimos lo siguiente, usando la \nnotación ( ) para insertar un carácter de nueva línea en la cadena del título:

awk -F: 'BEGIN {print "Cuentas de usuario \ n -------------"} $ 3> = 1000 {print $ 1, $ 6}' / etc / passwd

El comando "awk -F: 'BEGIN {print" User Accounts \ n ------------- "} $ 3> = 1000 {print $ 1, $ 6}' / etc / passwd" en una terminal ventana.

Los patrones son expresiones regulares en toda regla y son una de las glorias de awk.

Digamos que queremos ver los identificadores únicos universales (UUID) de los sistemas de archivos montados. Si buscamos en el /etc/fstabarchivo apariciones de la cadena “UUID”, debería devolvernos esa información.

Usamos el patrón de búsqueda «/ UUID /» en nuestro comando:

awk '/ UUID / {print $ 0}' / etc / fstab

El comando "awk '/ UUID / {print $ 0}' / etc / fstab" en una ventana de terminal.

Encuentra todas las apariciones de “UUID” e imprime esas líneas. De hecho, hubiéramos obtenido el mismo resultado sin la printacción porque la acción predeterminada imprime toda la línea de texto. Sin embargo, para mayor claridad, a menudo es útil ser explícito. Cuando revise un script o su archivo histórico, se alegrará de haber dejado pistas para usted.

La primera línea que se encontró fue una línea de comentario, y aunque la cadena “UUID” está en el medio, la awkencontré. Podemos modificar la expresión regular y decirle awkque procese solo las líneas que comienzan con «UUID». Para hacerlo, escribimos lo siguiente que incluye el token de inicio de línea ( ^):

awk '/ ^ UUID / {print $ 0}' / etc / fstab

El comando "awk '/ ^ UUID / {print $ 0}' / etc / fstab" en una ventana de terminal.

¡Eso es mejor! Ahora, solo vemos instrucciones de montaje genuinas. Para refinar aún más la salida, escribimos lo siguiente y restringimos la visualización al primer campo:

awk '/ ^ UUID / {imprimir $ 1}' / etc / fstab

El comando "awk '/ ^ UUID / {print $ 1}' / etc / fstab" en una ventana de terminal.

Si tuviéramos varios sistemas de archivos montados en esta máquina, obtendríamos una tabla ordenada de sus UUID.

Funciones integradas

awktiene muchas funciones que puede llamar y usar en sus propios programas , tanto desde la línea de comandos como en scripts. Si investiga un poco, lo encontrará muy fructífero.

Para demostrar la técnica general para llamar a una función, veremos algunas numéricas. Por ejemplo, lo siguiente imprime la raíz cuadrada de 625:

awk 'BEGIN {print sqrt (625)}'

Este comando imprime el arcotangente de 0 (cero) y -1 (que resulta ser la constante matemática, pi):

awk 'BEGIN {print atan2 (0, -1)}'

En el siguiente comando, modificamos el resultado de la atan2()función antes de imprimirlo:

awk 'BEGIN {print atan2 (0, -1) * 100}'

Las funciones pueden aceptar expresiones como parámetros. Por ejemplo, aquí hay una forma complicada de pedir la raíz cuadrada de 25:

awk 'BEGIN {print sqrt ((2 + 3) * 5)}'

El comando "awk 'BEGIN {print sqrt (625)}'" en una ventana de terminal.

guiones awk

Si su línea de comando se complica, o desarrolla una rutina que sabe que querrá usar nuevamente, puede transferir su awkcomando a un script.

Relacionado:  Cómo solucionar problemas de teclado y mouse Corsair en macOS y Linux

En nuestro script de ejemplo, haremos todo lo siguiente:

  • Dile al shell qué ejecutable usar para ejecutar el script.
  • Prepárese awkpara usar la FSvariable de separación de campos para leer el texto de entrada con campos separados por dos puntos ( :).
  • Use el OFSseparador de campo de salida para indicarle awkque use dos puntos ( :) para separar campos en la salida.
  • Establezca un contador en 0 (cero).
  • Establezca el segundo campo de cada línea de texto en un valor en blanco (siempre es una «x», por lo que no es necesario que la veamos).
  • Imprima la línea con el segundo campo modificado.
  • Incrementa el contador.
  • Imprime el valor del contador.

Nuestro guión se muestra a continuación.

Ejemplo de un script awk en un editor.

La BEGINregla realiza los pasos preparatorios, mientras que la  ENDregla muestra el valor del contador. La regla del medio (que no tiene nombre ni patrón para que coincida con todas las líneas) modifica el segundo campo, imprime la línea e incrementa el contador.

La primera línea del script le dice al shell qué ejecutable usar ( awken nuestro ejemplo) para ejecutar el script. También pasa la -fopción (nombre de archivo) a awk, que le informa que el texto que va a procesar vendrá de un archivo. Pasaremos el nombre del archivo al script cuando lo ejecutemos.

Hemos incluido el siguiente script como texto para que pueda cortar y pegar:

#! / usr / bin / awk -f

EMPEZAR {
  # establecer los separadores de campo de entrada y salida
  FS = ":"
  OFS = ":"
  # cero el contador de cuentas
  cuentas = 0
}
{
  # establecer el campo 2 en nada
  $ 2 = ""
  # imprime la línea completa
  imprimir $ 0
  # contar otra cuenta
  cuentas ++
}
FINAL {
  # imprimir los resultados
  imprimir cuentas "cuentas. \ n"
}

Guarde esto en un archivo llamado omit.awk. Para hacer que el script executabl correo , escribimos lo siguiente usando chmod:

chmod + x omit.awk

El comando "chmod + x omit.awk" en una ventana de terminal.

Ahora, lo ejecutaremos y pasaremos el /etc/passwdarchivo al script. Este es el archivo  awkque procesaremos por nosotros, usando las reglas dentro del script:

./omit.awk / etc / passwd

El comando "./omit.awk / etc / passwd" en una ventana de terminal.

El archivo se procesa y se muestra cada línea, como se muestra a continuación.

Salida de "./omit.awk / etc / passwd" en una ventana de terminal.

Las entradas «x» en el segundo campo se eliminaron, pero tenga en cuenta que los separadores de campo todavía están presentes. Las líneas se cuentan y el total se da en la parte inferior de la salida.

awk no significa incómodo

awkno significa incómodo; es sinónimo de elegancia. Se ha descrito como un filtro de procesamiento y un redactor de informes. Más exactamente, se trata de ambos o, mejor dicho, una herramienta que puede utilizar para ambas tareas. En solo unas pocas líneas,  awk logra lo que requiere una codificación extensa en un lenguaje tradicional.

Ese poder es aprovechado por el concepto simple de reglas que contienen patrones, que seleccionan el texto a procesar y acciones que definen el procesamiento.