¿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....


Cron es el nombre del programa que permite a usuarios Linux/Unix ejecutar automáticamente comandos o scripts (grupos de comandos)....


Traducción del capítulo del libro "Stealing the Network: How to Own a Continent." escrito por Fyodor, autor de nmap. Excelente a....


Muchos validadores de direcciones de correo electrónico devolverán errores cuando se enfrenten con una inusual pero válida dire....


¿Has visto esa combinación de r,w,x,- cuando listas un directorio?, tienes cierta idea que son los permisos, pero ¿como se usan....


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


La demanda civil entablada por la empresa SCO contra la gigante IBM causó revuelo entre la comunidad Linux y Open Source cuando e....


Imaginémonos a la empresa "Pato, S.A." que ofrece a sus empleados y clientes el sitio http://www.pato.com/consulta, donde mediant....


Observa la imagen siguiente, que corresponde a uno de los sitios de descargas de MySQL y notarás que todos los archivos que puede....



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