¿Requieres de una instalación o configuración de Linux o sus servicios?
¿Un desarrollo WEB empresarial a la medida?
¿Un curso o capacitación a la medida?
Revisa el sitio de SERVICIOS de LinuxTotal


Ejemplos de uso de awk o gawk 

Copyright © 2005-2024 LinuxTotal.com.mx
Se concede permiso para copiar, distribuir y/o modificar este documento siempre y cuando se cite al autor y la fuente de linuxtotal.com.mx y según los términos de la GNU Free Documentation License, Versión 1.2 o cualquiera posterior publicada por la Free Software Foundation.

Autor: Sergio González D.  

awk o la versión GNU gawk es más que un simple comando de procesamiento de patrones, es todo un lenguaje de análisis semántico. Su dominio es como aprender todo un lenguaje de programación, pero en esta ocasión veremos unos ejemplos de su potencia en unos casos sencillos de análisis de patrones de cadenas, espero te sirvan de base para que puedas aprender aun más sobre esta interesante herramienta.


Ejemplo 1: Una lista personalizada de usuarios para HTML

Una línea típica de /etc/passwd es como la siguiente:

luis:x:504:504:Luis Hernandez:/home/luis:/bin/bash

Bien, supongamos que deseamos un listado de todos los usuarios normales (personas) del sistema, pero solo necesitamos su nombre de usuario, su nombre o real y su shell por defecto, es decir, si vemos la línea anterior, la separación entre campos es ":" asi que para nuestro reporte queremos el campo 1,5 y 7. Pero además, este reporte será parte de una tabla HTML, asi que sería bueno si puderian incluirse de una vez las etquietas "<tr> y "<td> necesarias de una vez. Es decir, el resultado deseado es el siguiente:

<tr><td>luis<td><td>Luis Hernandez</td><td>/bin/bash</td></tr>

El primer paso es determinar los usuarios normales del sistema, podríamos usar un grep "home" /etc/passw | gawk ..., pero podría haber usuarios que tengan su HOME en otra ubicación, además se trata de usar solo awk, asi que lo primero que entenderemos es que los campos obtenidos del resultado de un comando awk, se numeran por $1, $2, etc. y el delimitador de campos se indica mediante la variable "FS".

#> gawk '{print $3}' FS=":" /etc/passwd
0
1
2
...
81
86
500
501
502
503
504

Aunque no muy útil todavía, podemos ver como seleccionamos el caracter separador FS=":", que viene de 'Field Separator', y tenemos indicada una acción '{print $3}', que significa imprime el campo 3. Aunque realmente no lo queremos imprimir, lo queremos evaluar, y si deseamos imprimir el $1, $5 y $7 que se mencionarion previamente, asi que agregamos una expresión de evaluación antes de la acción:

#> awk '$3 >= 500 {print $1 $5 $7 }' FS=":" /etc/passwd
sergonSergio Gonzalez/bin/bash
valeriaValeria Perez/bin/bash
fernandaFernanda Lozano/bin/sh
alejandraAlejandra Lopez/bin/nologin
luisLuis Hernandez/bin/bash

Mucho mejor, agregamos '$3 >= 500' previo a la acción (que es imprimir lo que deseamos), ya que como se sabe en la mayoría de distros modernas, los usuarios normales del sistema se numeran del 500 en adelante (más sobre administración de usuarios). Nótese que los campos en el resultado salen pegados, es necesario agregar entre comillas " ", ya sea un espacio o lo que se desee, en este caso etiquetas de tablas de HTML y además ordenaremos "sort" los registros obtenidos:

#> awk  '$3 >= 500 {print "<tr><td>"$1"</td><td>"$5"</td><td>"$7"</td></tr>" | "sort" }' FS=":" /etc/passwd
<tr><td>alejandra</td><td>Alejandra Lopez</td><td>/bin/nologin</td></tr>
<tr><td>fernanda</td><td>Fernanda Lozano</td><td>/bin/sh</td></tr>
<tr><td>luis</td><td>Luis Hernandez</td><td>/bin/bash</td></tr>
<tr><td>sergon</td><td>Sergio Gonzalez</td><td>/bin/bash</td></tr>
<tr><td>valeria</td><td>Valeria Perez</td><td>/bin/bash</td></tr>

Ejemplo 2: Una lista personalizado de usuarios para reporte

Ahora veamos como crear una lista similar a la anterior pero especificando un par de líneas de títulos al inicio:

#> awk 'BEGIN { print "Usuario UID Shell\n------- --- -----" } $3 >= 500 { print $1, $3, $7 | "sort -r"}' FS=":" /etc/passwd 
Usuario UID Shell
------- --- -----
valeria 501 /bin/bash
sergon 500 /bin/bash
luis 504 /bin/bash
fernanda 502 /bin/sh
alejandra 503 /bin/nologin

Iniciamos con la sentencia BEGIN (que tiene varios usos, checa el manual) que en este caso nos permite indicar lo que se imprimirá una sola vez, en este caso los títulos, un retorno '\n' y guiones para separar los títulos, después viene de nuevo la evaluación ya conocida y ahora al indicar la impresión de los campos 'print $1, $3, $7', los separé por comas, que automáticamente añade un espacio, y solo para aumentar el ejemplo, el ordenamiento es ahora al revés 'sort -r'.

Pero podemos ver en la salida, que los registros no se acomodan bien con respecto a los títulos, con dos o tres campos tal vez resulte fácil añadir espacios o tabuladores '\t' para hacer el acomodo, pero en varios campos será realmente frustrante lograrlo. Mejor usamos 'printf':

#> awk 'BEGIN { print "Usuario      UID Shell\n------------ ---- ----------" } $3 >= 500 \
  { printf "%12s %4d %10s\n", $1, $3, $7 | "sort -r"}' FS=":" /etc/passwd 
Usuario      UID Shell
------------ ---- ----------
     valeria  501  /bin/bash
      sergon  500  /bin/bash
        luis  504  /bin/bash
    fernanda  502    /bin/sh
   alejandra  503 /bin/nologin

Sigo usando 'print' para los títulos, pero ahora uso 'printf' que me permite formatear la salida, la sintaxis es 'printf "formato", $1, $2'. Cada formato comienza con '%' después el número de posiciones seguido del tipo de campo 's' para string, 'd' para enteros, etc. '%12s' 12 posiciones de tipo cadena. (checar el manual para el resto de formatos de printf), termino el formato con un salto de línea '\n'. Pero como se puede apreciar por defecto las cadenas se justifican a la derecha y en este caso las deseamos a la izquierda, esto se arregla agregando un '-' guión en el indicador de formato de la siguiente manera '%-12s', el resultado correcto sería el siguiente:

# awk 'BEGIN { print "Usuario      UID Shell\n------------ ---- ----------" } $3 >= 500 \
{ printf "%-12s %4d %-10s\n", $1, $3, $7 | "sort -r"}' FS=":" /etc/passwd 
Usuario      UID  Shell
------------ ---- ----------
valeria       501 /bin/bash 
sergon        500 /bin/bash 
luis          504 /bin/bash 
fernanda      502 /bin/sh   
alejandra     503 /bin/nologin

Ejemplo 3: Extrayendo campos sin posición fija

Hay ocasiones en que no se tiene exactamente la posición de los campos a extraer, asi que usaremos otra técnica basada en el número total de campos encontrados. En este caso, necesitamos la variable "NF" (Number of Fields) que representa el total de campos encontrados. Y usaremos como caracter separador FS el espacio, es decir FS=" ", pero dado que el espacio es el separador por defecto no es necesario indicarlo.

Como ejemplo, veamos la salida del comando uptime:

$> uptime
19:32:15 up  2:28,  1 user,  load average: 1.75, 1.54, 1.54

Y deseamos crear un pequeño script que de como resultado el siguiente:

$> ./carga
carga actual del sistema: 1min=1.75, 5min=1.54, 15min=1.54

Como se puede observar, se necesitan los tres últimos campos, aparentemente los campos $8, $9 y $10. Pero el problema esta en que conforme pasa el tiempo, el comando uptime mostrará de hecho más campos, ya que el que en este momento es el $3 '2:28' después de unos días puede quedar asi '3 days 3:50', asi que al usar NF nos dará el total de campos, veamos:

$> uptime | gawk '{print NF}'
10



$> uptime | gawk '{print $NF}'
1.33

Entendiendo lo anterior, es fácil de deducir entonces que los campos requeridos son entonces NF-2, NF-1, NF es decir, los tres últimos, y no importará cuantos campos haya en el resultado.

$> uptime | gawk '{print $(NF - 2), $(NF - 1), $NF}'
0.72, 0.54, 0.47

El script quedaría entonces así:

#!/bin/bash
echo "Carga actual del sistema: "
uptime | gawk '{print "1min:"$(NF - 2), "5min:"$(NF - 1), "15min:"$NF}'


¿Requieres de una instalación o configuración de Linux o sus servicios?
¿Un desarrollo WEB empresarial a la medida?
¿Un curso o capacitación a la medida?
Revisa el sitio de SERVICIOS de LinuxTotal

LinuxTotal en:

Si encuentras útil la información que proveé LinuxTotal, considera realizar un donativo que estimule a seguir proporcionando contenido de calidad y utilidad. Gracias.


Dona a través de paypal::


O a través de bitcoins:


14TNQv5wM3xkSv65gHGQ6s6f8yTZuFTohE
Más artículos de LinuxTotal

Hay ocasiones que los usuarios insisten en poner contraseñas muy débiles de 5 o 6 caracteres a lo más. Y el argumento que dan e....


...quien resuelve los nombres de dominio a su correspondiente IP, sería el DNS del proveedor, pero si implementamos un DNS Cache,....


Si acostumbras trabajar en la línea de comandos de Linux, muy posiblemente uses el shell bash (Bourne Again Shell, derivado del b....


Eventualmente, mientras más se aprende a usar la línea de comandos y a realizar shell scripts, en alguno de estos scripts necesi....


En Linux hay diversas herramientas para empaquetar y comprimir archivos, tomando en cuenta que empaquetar es juntar dos o más arc....


Ya no es nada raro que un centro de cómputo o en un site se encuentren varios sistemas Linux actuando como servidores de archivos....


En ambientes donde varios usuarios usan uno o más sistemas GNU/Linux, es necesario otorgar distintos permisos o privilegios para ....


Una de las dificultades con una base de datos MySQL grande y activa es la de realizar respaldos limpios sin tener que desconectar ....


Lo primero que debes hacer una vez que instalas un servidor de base de datos MySQL (casi todas las distros actuales lo instalan po....


En SQL, 'Alter' es un comando de la categoría DDL (Data Definition Language) y como su nombre lo indica sirve para alterar objeto....



Copyright © LinuxTotal.com.mx 2006-2024
info@linuxtotal.com.mx · linuxtotal.com.mx@gmail.com