COMIENZA y FINALIZA con el comando awk

13

Según el manual de awk, BEGIN y END no se utilizan para hacer coincidir la entrada, sino para proporcionar información de inicio y limpieza al script awk. Aquí está el ejemplo dado:

ls -l | \
awk 'BEGIN { print "Files found:\n" } /\<[a|x].*\.conf$/ { print $9 }'
Files found:
amd.conf
antivir.conf
xcdroast.conf
xinetd.conf

Primero, esto imprime una cadena a la salida. Luego verifica la entrada para una coincidencia de patrón, donde la entrada comienza con a o x seguido de cualquier carácter una o varias veces seguido de .conf. Para cualquier coincidencia, se imprime la novena columna.

El hecho de que nos veamos obligados a usar comienza aquí, ¿eso significa que awk solo puede usar como máximo una función de impresión que contenga un COMIENZO o FIN? Si no, ¿por qué no podemos usar la función de impresión al principio sin la palabra clave BEGIN? Parece que el COMIENZO es superfluo.

JohnMerlino
fuente
Simplemente ejecutando el comando sin BEGIN respondería su pregunta, mostrando que no es superflua y que obtendría un resultado diferente.
msb

Respuestas:

11

El BEGINno es superfluo. Si no se especifica BEGINa continuación, el printserían ejecutados por cada línea de entrada.

Citando del manual :

Una BEGINregla se ejecuta solo una vez, antes de leer el primer registro de entrada. Del mismo modo, una ENDregla se ejecuta solo una vez, después de leer toda la entrada.

$ seq 5 | awk 'BEGIN{print "Hello"}/4/{print}'   # Hello printed once
Hello
4
$ seq 5 | awk '{print "Hello"}/4/{print}'        # Hello printed for each line of input
Hello
Hello
Hello
Hello
4
Hello
$
devnull
fuente
7

awkprocesa cada línea de entrada para las expresiones dadas en el cuerpo que no sean BEGINy ENDbloques. En el caso de BEGINy ENDbloques, awkprocesará las declaraciones solo una vez, antes de que el procesamiento de entrada haya comenzado y después de que el procesamiento de entrada se haya realizado respectivamente. Sin el BEGINbloque, no solo no sería capaz de imprimir información de una sola vez, como encabezados, sino que no sería capaz de inicializar eficientemente algunas de las variables requeridas por el cuerpo. Además, para su información, un awkprograma puede tener múltiples BEGINy ENDbloques.

mkc
fuente
2

awkejecuta cada bloque solo cuando el patrón anterior coincide. El patrón vacío (solo bloque) coincide con cada línea. BEGINy ENDson patrones especiales que coinciden con el principio y el final del archivo (análogos al significado de ^y $en dirección horizontal).

Si desea ejecutar algo antes de leer el archivo, úselo BEGIN. Por ejemplo, inicialización de contadores o algo así. ENDLuego podría recoger los resultados.

Orión
fuente
0

En el ejemplo dado, que creo que está simplificado para la claridad pedagógica, tiene razón en que es superfluo. Podrías obtener los mismos resultados sin usar BEGIN.

1 == NR            { print "Files found:\n" }
/\<[a|x].*\.conf$/ { print $9               }

produciría los mismos resultados ya que la declaración de impresión está restringida solo a la primera línea de entrada.

Dicho esto, los bloques BEGINy ENDson herramientas increíblemente poderosas. Como han mencionado otras soluciones, puede usar el BEGINbloque para inicializar variables u otras rutinas que solo necesitan realizarse una vez, pero también pueden usarse para ejecutar comandos Awk cuando no hay archivos para procesar. Un simple ejemplo:

BEGIN { print sqrt(12/4) }

Puede ver un ejemplo más serio de programación en Awk sin procesar ninguna entrada aquí .

Del mismo modo, el ENDbloque es extremadamente útil para realizar cálculos y resumir toda la entrada. Esto no se puede hacer (generalmente) sin leer primero todos los datos. Un ejemplo simple de resumen de entrada se puede encontrar aquí

myq
fuente