Comprender cómo usar el comando AWK

AWK significa “Aho Weinberg Kernighan” y son los apellidos de las personas que lo inventaron: Alfred Aho, Peter Weinberg y Brian Kernighan. los Propósito de AWK es buscar archivos existentes para encontrar líneas que coincidan con ciertos patrones. Es un lenguaje de secuencias de comandos completo, así como un conjunto completo de herramientas de manipulación de texto. Está basado en datos, lo que significa que define un conjunto de acciones que se realizarán en el texto proporcionado y envía los resultados a la salida estándar.

Con AWK, podemos:

  • Escanea un archivo línea por línea.
  • Divida cada línea de entrada en campos.
  • Compare líneas o campos de entrada con patrones.
  • Realizar acciones en líneas coincidentes.

Los patrones se encierran entre barras (//), las acciones están encerradas entre llaves ({}), y todo el programa AWK está encerrado entre comillas simples (‘). El delimitador predeterminado para el comando awk es cualquier carácter de espacio en blanco como espacio o tabulación. Si no hay un patrón en el comando awk, todas las líneas del archivo proporcionado coincidirán.
Veamos el contenido de la carpeta actual con el comando ls -l.

[[email protected] public_html]$ ls -l
total 12
-rw-rw-r--. 1 mstevens mstevens 6426 Feb  9 08:00 access_log
-rw-rw-r--. 1 mstevens mstevens    0 Mar 19 04:48 config.php
-rw-r--r--. 1 mstevens mstevens 3661 Mar 19 04:31 dovecot.log
-rw-rw-r--. 1 mstevens mstevens    0 Mar 19 04:48 error_log
-rwxrwxrwx. 1 mstevens mstevens    0 Mar 19 04:49 everyone.txt
-rw-rw-r--. 1 mstevens mstevens    0 Mar 19 04:48 index.php
-rw-rw-r--. 1 mstevens mstevens    0 Mar 19 04:49 list.php
-rw-rw-r--. 1 mstevens mstevens    0 Mar 19 04:49 login.php
-rw-rw-r--. 1 mstevens mstevens    0 Mar 24 03:14 php.ini

La salida del comando ls muestra el número total de bloques (que en este caso es 12) y contiene nueve campos (de izquierda a derecha):

  1. permisos
  2. El número de conexiones
  3. Usuario
  4. Grupo
  5. Tamaño
  6. Mes
  7. Día
  8. Hora de la última actualización
  9. Nombre del archivo

Si por examplesolo necesitamos imprimir permisos y nombres de archivo, podemos canalizar el comando ls -l a AWK y decirle que imprima el primer y el noveno campo.
El programa AWK simple a continuación no tiene patrón, solo acciones, por lo que revisará y combinará cada línea de texto proporcionada mostrando solo el primer y el noveno campo en cada línea.

[[email protected] public_html]$ ls -l | awk '{print $1,$9}'
total
-rw-rw-r--. access_log
-rw-rw-r--. config.php
-rw-r--r--. dovecot.log
-rw-rw-r--. error_log
-rwxrwxrwx. everyone.txt
-rw-rw-r--. index.php
-rw-rw-r--. list.php
-rw-rw-r--. login.php
-rw-rw-r--. php.ini

Como puede ver, la salida del comando ls tiene 10 líneas de texto, incluida la línea con la palabra total. La palabra total es el primer campo en su línea, y el número 12 era el segundo campo en su línea. Solo total se devuelve en la salida porque el comando awk solicitó los campos primero y noveno. Para evitar la coincidencia de líneas que no son necesarias, podemos proporcionar un patrón y solo se generarán líneas con este patrón.

La coincidencia de patrones

Patrones en AWK se utilizan para mostrar acciones específicas en líneas que coinciden con un patrón dado. Lo mismo se puede lograr con un comando grep para encontrar cierta información en el texto o los archivos proporcionados. La única diferencia es que no necesitamos combinar varios comandos; solo necesitamos usar un comando awk.

AWK admite diferentes tipos de patrones:

  • Patrones de expresiones regulares
  • Patrones de expresión de relación
  • Patrones de rango
  • Expresiones especiales

Patrones de expresiones regulares

lo mas basico example es coincidencia de cadenas. Si queremos obtener solo líneas con la palabra php, podemos agregar un patrón en el comando awk entre barras (//). Como se muestra a continuación, no importa dónde esté la palabra php se encuentra en la línea, esos archivos se muestran en la salida.

[[email protected] public_html]$ ls -l | awk '/php/ {print $1,$9}'
-rw-rw-r--. config.php
-rw-rw-r--. index.php
-rw-rw-r--. list.php
-rw-rw-r--. login.php
-rw-rw-r--. php.ini

Caracteres de sintaxis Regex

Una expresión regular es un patrón que describe una cierta cantidad de texto. Para no confundirlo con “Patrón de expresión regular”, que es uno de los patrones awk, usaré “regex”, que también se usa ampliamente en TI.

Ciertos caracteres tienen significados especiales cuando se usan en expresiones regulares.

anclas

Los anclas no coinciden con ningún carácter. En su lugar, coinciden con una posición anterior o posterior a los caracteres.

Ver tabla

AnclaFunción
^Indica el comienzo de la línea.
PSIndica el final de una línea.
AIndica el principio de una cadena.
conIndica el final de una cadena.
BMarca un límite de palabra.

Caracteres

Puede hacer coincidir caracteres que siguen reglas específicas.

Ver tabla

PersonajeFunción
[ae]Selecciona a o mi.
[a-e]Selecciona cualquier carácter de la a a la e (a, b, c, d o e).
[^a-e]Selecciona cualquier personaje excepto a a e (f, g, h, etc.).
wSelecciona cualquier palabra.
sSelecciona cualquier carácter de espacio en blanco.
BSelecciona cualquier dígito.

cuantificadores

Los cuantificadores especifican cuántas instancias de un personaje, grupo o clase de personaje deben estar presentes en la entrada para que se encuentre una coincidencia.

Ver tabla

cuantificadorFunción
.Coincide con cualquier carácter.
+Modifica el conjunto anterior una o más veces.
*Modifica el conjunto precedente cero o más veces.
?Modifica el conjunto precedente cero o una vez.
{norte}Modifica el conjunto anterior exactamente n veces.
{norte,}Modifica el conjunto anterior n o más veces
{Nuevo Méjico}Modifica el conjunto precedente entre n y m veces.

Con esta información, ahora podemos usarla para encontrar todos los archivos PHP. Podemos usar /php$/ en el comando para encontrar todas las líneas que terminan con php.

[[email protected] public_html]$ ls -l | awk '$9 ~ /php$/ {print $1,$9}'
-rw-rw-r--. config.php
-rw-rw-r--. index.php
-rw-rw-r--. list.php
-rw-rw-r--. login.php

En la carpeta actual, solo hay cuatro archivos PHP. El archivo php.ini fue excluido porque php no está al final de la cadena.

Patrones de expresión relacional

De forma predeterminada, los patrones de expresiones regulares se comparan con toda la línea. Los patrones de expresión relacional hacen coincidir el contenido de un campo específico con el patrón proporcionado.

Para hacer coincidir un patrón con un campo, necesitaríamos especificar el operador de comparación (~) con un patrón:

  • Líneas de coincidencia: $n ~ /patrón/
  • Líneas no coincidentes: $n !~ /patrón/

El marcador de posición $n es el número de campos utilizados para coincidir con el patrón proporcionado. Ahora usemos nuestro anterior example.

ls -l | awk '$9 ~ /php/ {print $1,$9}

El $9 ~ /php/ hará coincidir el noveno campo con la palabra php.

[[email protected] public_html]$ ls -l | awk '$9 ~ /php/ {print $1,$9}'
-rw-rw-r--. config.php
-rw-rw-r--. index.php
-rw-rw-r--. list.php
-rw-rw-r--. login.php
-rw-rw-r--. php.ini

Si intentara usar el primer campo (permisos) no obtendría ningún resultado ya que el primer campo solo contiene caracteres como -rwxr-xr–. (que significa leer, escribir, ejecutar).

[[email protected] public_html]$ ls -l | awk '$1 ~ /php/ {print $1,$9}'
[[email protected] public_html]$

Patrones de rango

Los patrones de rango constan de dos patrones separados por una coma. Esto nos permite imprimir todos los registros desde la línea que coincide con el primer patrón hasta que coincide con el segundo patrón.

/pattern1/, /pattern2/

En esto example Quiero imprimir todos los archivos desde la línea que coincide con la configuración hasta el archivo que coincide con el índice. El comando se muestra a continuación.

[[email protected] public_html]$ ls -l | awk '/config/,/index/ { print $0 }'
-rw-rw-r--. 1 mstevens mstevens    0 Mar 19 04:48 config.php
-rw-r--r--. 1 mstevens mstevens 3661 Mar 19 04:31 dovecot.log
-rw-rw-r--. 1 mstevens mstevens    0 Mar 19 04:48 error_log
-rwxrwxrwx. 1 mstevens mstevens    0 Mar 19 04:49 everyone.txt
-rw-rw-r--. 1 mstevens mstevens    0 Mar 19 04:48 index.php

También podríamos unir caracteres en líneas que siguen reglas definidas. Digamos que desea encontrar todas las líneas que contienen la letra yoseguido de la letra O o I. Crea el siguiente comando.

[[email protected] public_html]$ ls -l | awk '$9 ~ /l[oi]/ {print $1,$9}'
-rw-rw-r--. access_log
-rw-r--r--. dovecot.log
-rw-rw-r--. error_log
-rw-rw-r--. list.php
-rw-rw-r--. login.php

Como se muestra arriba, Iniciar sesión, listay acceso son las palabras que coinciden con expresiones regulares utilizadas en el comando awk.

Los cuantificadores se pueden usar si hay cierto carácter que se repite en el texto proporcionado. He creado un archivo con el siguiente contenido.

[[email protected] public_html]$ cat test.txt
1. a b c d
2. d c b a
3. aa bb cc dd
4. dd cc bb aa
5. aaa bbb ccc ddd
6. ddd ccc bbb aaa

Para encontrar todas las líneas que contienen tres a caracteres (aaa) y tener al menos una posterior C personaje, usaría el siguiente comando.

awk '/a{3}.*c/ {print $0}' test.txt

La salida indica que una línea contiene aaa con al menos un carácter C siguiendo después.

[[email protected] public_html]$ awk '/a{3}.*c/ {print $0}' test.txt
5. aaa bbb ccc ddd

Expresiones especiales

Las variables dentro de AWK se pueden configurar en cualquier línea del programa. AWK incluye los siguientes patrones especiales:

  • BEGIN – Realiza su acción correspondiente antes de que se lea el primer registro y generalmente se utiliza para definir variables para todo el programa.
  • FIN: realiza su acción después de leer el último registro del archivo de entrada.

AWK tiene varias variables integradas que le permiten controlar cómo se procesa el programa. Estas son algunas de las variables integradas más comunes.

Ver tabla

VariableFunción
NFEl número de campos en el registro.
NOEl número del registro actual.
NOMBRE DEL ARCHIVOEl nombre del archivo de entrada que se procesa actualmente.
FSSeparador de campos.
RSSeparador de registros.
OFSSeparador de campo de salida.
SROSeparador de registros de salida.

Ahora usemos NR en nuestro comando para verificar la cantidad de líneas en test.txt. Como vemos a continuación, hay seis líneas dentro del archivo.

[[email protected] public_html]# awk 'END { print FILENAME, "contains", NR, "lines." }' test.txt
test.txt contains 6 lines.

Cambiar el separador

El separador es cualquier carácter que divide líneas de texto en campos. El separador de campo predeterminado es cualquier cantidad de caracteres de espacio en blanco como espacio o tabulación, pero puede cambiar el separador con la variable FS o el indicador -F en el comando awk.

Uso de la variable FS

Primero, mostraremos cómo usar la variable FS. A continuación tenemos las líneas actuales en test.txt con los campos separados por espacios en blanco.

[[email protected] public_html]$ cat test.txt
1. a b c d
2. d c b a
3. aa bb cc dd
4. dd cc bb aa
5. aaa bbb ccc ddd
6. ddd ccc bbb aaa

Para facilitar la lectura, la siguiente imagen muestra la información anterior, con los espacios en blanco resaltados en verde.

Ahora, separaré los campos por el C carácter e imprimir el primer campo. Esto significa que los espacios en blanco existentes ya no separarán cada campo y serán caracteres normales. Todo antes del primero C en una línea formará parte del primer campo y se imprimirá. Toda la información restante en las líneas forma parte de los campos posteriores y no se incluirá en la salida.

[[email protected] public_html]$ awk 'BEGIN { FS = "c" } { print $1 }' test.txt
1. a b
2. d
3. aa bb
4. dd
5. aaa bbb
6. ddd

Nuevamente, tenemos la salida de arriba que se muestra a continuación con el separador (C).

Como el separador crea un campo adicional, el número de C‘s en una línea aumentará el número de campos presentes. Dos campos están presentes en las líneas 1 y 2, tres campos están presentes en las líneas 3 y 4, y cuatro campos están presentes en las líneas 5 y 6. Podemos verlo mejor en la imagen a continuación. El área entre cada separador verde representa un campo adicional.

fs-variable-c-separador-todos-los-campos

Uso de la bandera -F

Ahora cambiaremos el separador en un comando awk usando el indicador -F y trabajaremos con otro example.

awk -F'c' '{ print $1 }' test.txt

A continuación se muestra el contenido de nuestra carpeta anterior de antes en el artículo.

[[email protected] public_html]$ ls -l
total 12
-rw-rw-r--. 1 mstevens mstevens 6426 Feb  9 08:00 access_log
-rw-rw-r--. 1 mstevens mstevens    0 Mar 19 04:48 config.php
-rw-r--r--. 1 mstevens mstevens 3661 Mar 19 04:31 dovecot.log
-rw-rw-r--. 1 mstevens mstevens    0 Mar 19 04:48 error_log
-rwxrwxrwx. 1 mstevens mstevens    0 Mar 19 04:49 everyone.txt
-rw-rw-r--. 1 mstevens mstevens    0 Mar 19 04:48 index.php
-rw-rw-r--. 1 mstevens mstevens    0 Mar 19 04:49 list.php
-rw-rw-r--. 1 mstevens mstevens    0 Mar 19 04:49 login.php
-rw-rw-r--. 1 mstevens mstevens    0 Mar 24 03:14 php.ini

Al utilizar algunos registros de dovecot.log, podemos determinar si alguien está tratando de acceder a las cuentas de correo electrónico incorporando el comando awk. Tenemos ejemplos de conexiones fallidas y exitosas.

Ver tabla

Conexión fallidaConexión exitosa
19 de marzo 04:21:20 host dovecot: imap-login: Desconectado (autorización fallida, 1 intento en 2 segundos): usuario=, método=PLAIN, rip=50.50.50.50, lip=5.6. 7.8, TLS, TLSv1.2 con cifrado ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits), session=19 de marzo 04:37:33 host dovecot: imap-login: Login: user=, method=PLAIN, rip=1.2.3.4, lip=5.6.7.8, mpid=20273, TLS, TLSv1. 2 con cifrado ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits), session=

No es bonito, pero podemos dividir la salida de la conexión en partes más pequeñas. Los valores más importantes en estos registros en los que centrarse son:

  • imap-login: indica que alguien intentó iniciar sesión en una cuenta de correo electrónico.
  • user= – Muestra a qué cuenta de correo electrónico intenta acceder esa persona.
  • rip= – La IP que está intentando conectarse.

El siguiente comando generará todas las direcciones IP que no pudieron conectarse a una cuenta de correo electrónico.

[[email protected] public_html]$ awk -F'rip=' '/imap-login/&&/failed/ {print $1, $2}' dovecot.log | awk -F'user=' '{print $2}' | awk -F, '{print $3,$1}'
  127.0.0.1 <[email protected].com>
  127.0.0.1 <[email protected]>
  127.0.0.1 <[email protected]>
  50.50.50.50 <[email protected]>
  50.50.50.50 <[email protected]>
  50.50.50.50 <[email protected]>
  50.50.50.50 <[email protected]>
  50.50.50.50 <[email protected]>
  50.50.50.50 <[email protected]>
  50.50.50.50 <[email protected]>
  50.50.50.50 <[email protected]>
  50.50.50.50 <[email protected]>

Si ve actividad sospechosa, alguien podría estar intentando un ataque de fuerza bruta en su servidor. Actualice su(s) contraseña(s) lo antes posible y tome medidas para evitar ataques en el futuro, como implementar la autenticación de dos factores (2FA) y habilitar CAPTCHA.

Usando AWK con sub() y gsub()

AWK presenta varias funciones que realizan acciones de búsqueda y reemplazo como el comando sed. La función sub sustituye la primera entidad coincidente en un registro con una cadena proporcionada. Voy a mostrar esto en el archivo test.txt.

La parte del comando que dice sub(/a/, “X”, $2); sustituirá la letra a con una carta X en el segundo campo. Solo la primera, tercera y quinta líneas se verán afectadas ya que las líneas contienen la letra a en el segundo campo.

[[email protected] public_html]$ awk '{sub(/a/, "X", $2); print $0}' test.txt
1. X b c d
2. d c b a
3. Xa bb cc dd
4. dd cc bb aa
5. Xaa bbb ccc ddd
6. ddd ccc bbb aaa

Si bien este cambio solo se mostrará en la terminal y no cambiará el archivo, podemos redirigir la salida a un archivo diferente para guardar los cambios. La subfunción se usa cuando necesitamos reemplazar cierta información dentro de un archivo, como la URL de un sitio en archivos sql, mientras se conserva el archivo sql original.

La segunda función es gsub y, aunque tiene la misma sintaxis, la única diferencia es que reemplazará todos los valores que se encuentran en los campos provistos, no solo el primer carácter. Nuevamente, las líneas primera, tercera y quinta se ven afectadas, pero en lugar de solo la primera a carácter en la línea cambiando a Xtodo a los caracteres del primer campo se cambian a X.

[[email protected] public_html]$ awk '{gsub(/a/, "X", $2); print $0}' test.txt
1. X b c d
2. d c b a
3. XX bb cc dd
4. dd cc bb aa
5. XXX bbb ccc ddd
6. ddd ccc bbb aaa

Conclusión

AWK es una poderosa herramienta que puede reemplazar comandos como grep, sed y muchos otros para encontrar patrones dentro de los archivos. Dependiendo de lo que se necesite, todos los patrones se pueden cambiar para generar la información deseada. ¡Pruebe los comandos mencionados en este artículo en su propio servidor y vea qué patrones puede encontrar!

Para obtener más información sobre las soluciones de Liquid Webs, visite nuestra página de descripción general del producto para obtener más información. Nuestra línea de productos de hospedaje administrado es lo suficientemente sólida para empresas de todos los tamaños, desde nuevas empresas en etapa inicial hasta empresas maduras que requieren entornos de hospedaje empresarial.

Related Posts