En Linux, awk
es un dínamo de manipulación de texto de línea de comandos, así como un poderoso lenguaje de secuencias de comandos. Aquí hay una introducción a algunas de sus características más interesantes.
RELACIONADO: 10 comandos básicos de Linux para principiantes
Cómo awk consiguió su nombre
los awk
El 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 AT&T Laboratorios Bell Panteón Unix. Con las contribuciones de muchos otros desde entonces, awk
ha seguido evolucionando.
Es un lenguaje de secuencias de comandos completo, así como un conjunto de herramientas de manipulación de texto completo para la línea de comandos. Si este post le abre el apetito, puede mira cada detalle sobre awk
y su funcionalidad.
Reglas, patrones y acciones
awk
trabaja 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. La totalidad awk
El programa está entre comillas simples ('
).
Echemos un vistazo al tipo más simple de awk
programa. 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. Bien úselo en la salida de los who
mando.
Aquí está la salida estándar de who
:
who
Tal vez no necesitemos toda esa información, sino más bien, solo queremos ver los nombres en las cuentas. Podemos canalizar la salida desde who
dentro awk
y posteriormente decir awk
para imprimir solo el primer campo.
Por defecto, awk
considera 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, $1
representa el primer campo, que usaremos con el print
acción para imprimir el primer campo.
Escribimos lo siguiente:
who | awk '{print $1}'
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, awk
imprime un espacio entre cada campo.
Escribimos lo siguiente para imprimir además la hora en que la persona inició sesión (campo cuatro):
who | awk '{print $1,$4}'
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:
cat dennis_ritchie.txt
Queremos awk
para imprimir el primer, segundo y último campo de la cotización. Tenga en cuenta que, aún cuando está envuelto en la ventana de la terminal, es solo una línea de texto.
Escribimos el siguiente comando:
awk '{print $1,$2,$NF}' dennis_ritchie.txt
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 utilizar $NF
para obtener su valor. El período se considera simplemente otro carácter en el cuerpo del campo.
Agregar separadores de campo de salida
Además puedes decir awk
para imprimir un carácter particular entre campos en lugar del carácter de espacio predeterminado. La salida predeterminada del date
el comando es un poco peculiar debido a que el tiempo se coloca justo en el medio. A pesar de esto, podemos escribir lo siguiente y utilizar awk
para extraer los campos que queremos:
date
date | awk '{print $2,$3,$6}'
Usaremos el OFS
(separador de campo de salida) variable para colocar 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 llaves ({}
):
date | awk 'OFS="https://www.systempeaker.com/" {print$2,$3,$6}'
date | awk 'OFS="-" {print$2,$3,$6}'
Las reglas BEGIN y END
A BEGIN
La regla se ejecuta una vez antes de que comience el procesamiento de texto. En realidad, se ejecuta antes awk
inclusive lee cualquier texto. Un END
La regla se ejecuta después de que se haya completado todo el procesamiento. Puedes tener varios BEGIN
y END
reglas, y se ejecutarán en orden.
Para nuestro ejemplo de BEGIN
regla, imprimiremos la cita completa de la dennis_ritchie.txt
archivo que usamos previamente con un título encima.
Para hacerlo, escribimos este comando:
awk 'BEGIN {print "Dennis Ritchie"} {print $0}' dennis_ritchie.txt
Nota la BEGIN
La regla tiene su propio conjunto de acciones encerradas dentro de su propio conjunto de llaves ({}
).
Podemos utilizar esta misma técnica con el comando que usamos previamente para canalizar la salida de who
dentro awk
. Para hacerlo, escribimos lo siguiente:
who | awk 'BEGIN {print "Active Sessions"} {print $1,$4}'
Separadores de campo de entrada
Si deseas awk
para trabajar con texto que no utiliza espacios en blanco para separar campos, debe indicarle qué carácter utiliza el texto como separador de campo. A modo de ejemplo, el /etc/passwd
el archivo utiliza dos puntos (:
) para separar campos.
Usaremos ese archivo y el -F
(cadena de separación) opción para decir awk
utilizar los dos puntos:
) como separador. Escribimos lo siguiente para contar awk
para imprimir el nombre de la cuenta de usuario y la carpeta de inicio:
awk -F: '{print $1,$6}' /etc/passwd
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).
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 ID de usuario Si los números son iguales o superiores a 1.000, podemos basar nuestro filtro en esa información.
Escribimos lo siguiente para ejecutar nuestra acción de impresión solo cuando el tercer campo ($3
) contiene un valor de 1000 o más:
awk -F: '$3 >= 1000 {print $1,$6}' /etc/passwd
El patrón debe preceder inmediatamente a la acción con la que está relacionado.
Podemos utilizar el BEGIN
regla para proporcionar un título a nuestro pequeño reporte. Escribimos lo siguiente, usando el (n
) notación para insertar un carácter de nueva línea en la cadena del título:
awk -F: 'BEGIN {print "User Accountsn-------------"} $3 >= 1000 {print $1,$6}' /etc/passwd
Los patrones son completos expresiones regulares, 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 a través del /etc/fstab
archivo para 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
Encuentra todas las apariciones de “UUID” e imprime esas líneas. En realidad, hubiéramos obtenido el mismo resultado sin el print
acción debido a que la acción predeterminada imprime toda la línea de texto. A pesar de esto, 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, aún cuando la cadena «UUID» está en el medio, awk
aún lo encontré. Podemos modificar la expresión regular y decir awk
para procesar 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
¡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/ {print $1}' /etc/fstab
Si tuviéramos varios sistemas de archivos montados en esta máquina, obtendríamos una tabla ordenada de sus UUID.
Funciones integradas
awk
tiene 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. A modo de 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. A modo de ejemplo, aquí hay una forma complicada de pedir la raíz cuadrada de 25:
awk 'BEGIN { print sqrt((2+3)*5)}'
guiones awk
Si su línea de comando se complica o desarrolla una rutina que sabe que querrá utilizar nuevamente, puede transferir su awk
comando en un script.
En nuestro script de ejemplo, haremos todo lo siguiente:
- Dígale al shell qué ejecutable utilizar para ejecutar el script.
- Preparar
awk
utilizar elFS
variable de separación de campo para leer el texto de entrada con campos separados por dos puntos (:
). - Usar el
OFS
separador de campo de salida para contarawk
utilizar 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.
los BEGIN
regla lleva a cabo los pasos preparatorios, mientras que el END
La regla muestra el valor del contador. La regla del medio (que no tiene nombre ni patrón, por lo que coincide 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 utilizar (awk
, en nuestro ejemplo) para ejecutar el script. Además pasa el -f
(nombre de archivo) opción para 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 BEGIN { # set the input and output field separators FS=":" OFS=":" # zero the accounts counter accounts=0 } { # set field 2 to nothing $2="" # print the entire line print $0 # count another account accounts++ } END { # print the results print accounts " accounts.n" }
Guarda esto en un archivo llamado omit.awk
. Para hacer que el script sea ejecutablemi, escribimos lo siguiente usando chmod
:
chmod +x omit.awk
Ahora, lo ejecutaremos y pasaremos el /etc/passwd
archivo a la secuencia de comandos. Este es el archivo awk
procesará por nosotros, usando las reglas dentro del script:
./omit.awk /etc/passwd
El archivo se procesa y se muestra cada línea, como se muestra a continuación.
Se eliminaron las entradas «x» en el segundo campo, pero tenga en cuenta que los separadores de campo aún 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
awk
no significa incómodo; es sinónimo de elegancia. Se ha descrito como un filtro de procesamiento y un redactor de informes. Más exactamente, son ambos o, mejor dicho, una herramienta que puede usar para ambas tareas. En solo unas pocas líneas, awk
logra lo que necesita 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.
setTimeout(function(){
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version=’2.0′;
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s) } (window, document,’script’,
‘https://connect.facebook.net/en_US/fbevents.js’);
fbq(‘init’, ‘335401813750447’);
fbq(‘track’, ‘PageView’);
},3000);