awk programming
awk 'BEGIN{print "hola";}'
awk ' (ENTER)
> BEGIN {
> print "one"
> }' (ENTER)
awk -f process.awk
awk -f process.awk file_input
La condición y el inicio de su acción deben estar en la misma línea, no pueden estar separadas. En caso de estar separadas hay que escapar con un backslash \
:
/onActionFromEdit/ \
{
printf "[%s] %s\n",FILENAME,$0;
}
# Otra manera
/onActionFromEdit/ {
printf "[%s] %s\n",FILENAME,$0;
}
awk -F,
: Indica que el separador de columnas es la ,
Los archivos csv exportan todos los valores con comillas, con gsub(/"/,"",$0);
se quitan:
awk -F, '{gsub(/"/,"",$0); print $2}' values.csv
awk también puede realizar un procesamiento de texto sin un archivo de texto de por medio, en el siguiente código recoge el texto de otro comando:
echo "carlos" | awk '{print "hola", $0 }'
Forma 1:
awk -f process.awk *
Forma 2:
process.sh
:
for f in *; do
awk '/pattern/ {print}' $f
done
awk '{print $0)' file1.txt file2.txt
: primero procesa file1.txt
y cuando termina procesa file2.txt
NR==FNR{print "primer archivo:",$0}
: condición para saber si se está procesando el primer archivo.
NR!=FNR{print "segundo archivo:",$0}
: condición para saber si se está procesando el segundo archivo.
awk 'BEGIN {action}
condition {action;}
END {action} input_file'
BEGIN{}
: Se ejecuta antes de procesar el archivo
condition
: En este espacio acepta una condición (exp booleana), si evalúa a true
ejecutará el cuerpo {}
. Por ejemplo, si solo quisieramos que se escriba la tercer fila: NR==3{print "tercer fila:",$0} file1.txt
.
Si se envía una expresión regular /search/ {}
, se ejecuta cada que una línea hace match con /search/
Si no tiene condición evalúa a true
y se ejecuta la acción.
Pueden existir N condiciones, cada una con su respectiva acción.
{}
: la acción por defecto es print
END{}
: Se ejecuta cuando termina de procesar el archivo
input_file
: Archivo a procesar (solo se puede enviar 1 archivo, no acepta directorios)
$0
: Toda la línea
$1
: Primer columna
$2
: Segunda columna
$3
: Tercer columna
$NF
: Última columna
Las cadenas se representan SIEMPRE con ""
.
En awk no se utiliza un operador para concatenar cadenas:
i=9; print "hola ("i") mundo"
String functions - ejemplos simples
gsub
: global substitution sirve para hacer un remplazo de todas las coincidencias
gsub(/regex-find/,replacement, string);
: busca la regex
y lo remplaza con replacement
en el string
indicado (puede ser una columna).
gsub(",","",$0); print $0
: Quita las comas de toda la línea
text="hola mundo nombre,nombre";
gsub("nombre", "carlos", text);
print text;
Output: hola mundo carlos,carlos
sub
: Funciona igual que gsub
pero solo remplaza la primer ocurrencia encontrada de izquierda a derecha.
text="hola mundo nombre,nombre";
sub("nombre", "carlos", text);
print text;
Output: hola mundo carlos,nombre
str = "One,Two,Three,Four"
split(str, arr, ",")
print "Array contains following values"
for (i in arr) {
print arr[i]
}
Por automático agrega un salto de línea al final
# Ambos imprimen toda la línea
print
print $0
world="mundo"
name="carlos"
print "hola " world " de " name
# prints: hola mundo de carlos
print "hola","carlos"`: imprime `hola carlos` (la `,` agrega por automático el espacio)
Sirve para imprimir una cadena formateada (texto/fecha/número/hora/moneda). Por defecto no agrega un salto de línea al final.
printf "hola (%s) mundo\n",5
Por defecto el separador de columnas es:
awk -F| ...
: Cambiar el separador de columnas por defecto por |
:
# comentario
El valor de una expresión es siempre un Entero
o un String
.
Some contexts (such as arithmetic operators) require numeric values. They convert strings to numbers by interpreting the text of the string as a number. If the string does not look like a number, it converts to zero.
Other contexts (such as concatenation) require string values. They convert numbers to strings by effectively printing them with sprintf. See section Conversion of Strings and Numbers, for the details.
To force conversion of a string value to a number, simply add zero to it. If the value you start with is already a number, this does not change it.
To force conversion of a numeric value to a string, concatenate it with the null string.
Comparisons are done numerically if both operands are numeric, or if one is numeric and the other is a numeric string. Otherwise one or both operands are converted to strings and a string comparison is performed. Fields, getline input, FILENAME, ARGV elements, ENVIRON elements and the elements of an array created by split are the only items that can be numeric strings. String constants, such as "3.1415927" are not numeric strings, they are string constants. The full rules for comparisons are described in section Variable Typing and Comparison Expressions.
Uninitialized variables have the string value "" (the null, or empty, string). In contexts where a number is required, this is equivalent to zero.
Como solo existen enteros y Strings:
0
: false
1
: true
Por ejemplo:
$0~/ERROR/ # Retorna 1 si hace match, 0 si no hace match
/regex/
La línea $0
CONTIENE la regex
/sa/
: La línea $0
CONTIENE sa
.
$0 ~ "sa"
: La línea $0
CONTIENE sa
(funciona igual que la línea anterior)
$0 ~ /sa/
: La línea $0
CONTIENE sa
(funciona igual que la línea anterior)
$0 ~ /"sa"/
: La línea $0
CONTIENE sa
(funciona igual que la línea anterior)
$0 !~ /sa/
: La línea $0
NO CONTIENE sa
/^sa/
: La línea $0
COMIENZA con sa
.
$0 !~ /^sa/
: La línea $0
NO COMIENZA con sa
$0 == "[DEBUG] AbstractControlNode - [ENTER] onActionFromEdit"
: La línea ES EXACTAMENTE IGUAL a la cadena
$0 ~ /\[DEBUG\] AbstractControlNode \- \[ENTER\] onActionFromEdit/
: La línea CONTIENE LA CADENA (es necesario escapar los caracteres especiales de la regex)
index($0, "[DEBUG] AbstractControlNode - [ENTER] onActionFromEdit")!=0
: La línea CONTIENE LA CADENA (la cadena no es una regex por lo que no se tiene que escapar)
index($0, "[DEBUG] AbstractControlNode - [ENTER] onActionFromEdit")==0
: La línea NO CONTIENE LA CADENA (la cadena no es una regex por lo que no se tiene que escapar)
match("busca aqui (regex)", "usca")
: Retorna el índice de el primer match de la regex
en el string str
. Retorna 0 si no encuentra un match. Los índices comienzan en 1
, en el ejemplo retorna 2
.
Asignar un valor:
map["key"]=value
recorrer el mapa:
for(key in map) {
value=map[key];
}
Busca si la llave está dentro del mapa:
if (key in map){}
Remove element:
delete map["key"];
Regularmente los arrays en los lenguajes de programación son de tamaño fijo y con índices contiguos(0,1,2,...). En awk los arrays son asociativos (mapas), es decir, los índices pueden ser enteros
o strings
y si son enteros no tienen por qué ser contiguos. Por convensión, los arrays que tienen índices enteros empiezan desde el índice 1
.
Recorrer un array:
for (idx in array){
value = array[idx];
}
Validar si existe un índice dentro del array:
if (indx in array)
Obtiene el tamaño del array:
function len(a) {
i=0;
for(k in a){
i++;
}
return i;
}
Eliminar un elemento del array:
delete foo[4];
Las funciones que existen en awk para hacer sort tienen un comportamiento un tanto "extraño" ya que sort
en sus 3 versiones ordena los valores de un array asociativo pero destruye los índices (llaves), mientras que sorti
ordena los índices del array asociativo y luego los pasa a los valores destruyendo en este caso los valores antiguos.
La manera más natural de ordenar elementos en awk es a través de PROCINFO["sorted_in"]
ya que en vez de ordenar y modificar el array, se indica la manera en la que awk recorrerá todos los arrays asociativos en los for(i in array){}
.
asort: Esta función ordena los valores del array. Por defecto toma los valores como String
o como Entero
dependiendo del tipo de dato definido en el valor.
asorti: Esta función ordena los índices del array. Por defecto toma los índices como fueran Strings
(no importa que sean enteros), por lo tanto ordena los índices como cadenas: 1 10 3
.
A continuación se describen las diferentes versiones de asort
/asorti
, ambas tienen 3 versiones con los mismos argumentos, sin embargo por simplicidad solo se explica las funciones de asort
.
asort(a)
: Ordena los valores del array a
y remplaza los índices con enteros secuenciales empezando por 1:
a["last"]="de";
a["first"]="sac";
a["middle"]="cul";
asort(a);
OUTPUT
a[1] = "cul";
a[2] = "de";
a[3] = "sac";
asorti(a)
: Ordena los índices del array a
y los pasa a los valores, remplaza los índices con enteros secuenciales empezando por 1:
a["last"]="de";
a["first"]="sac";
a["middle"]="cul";
asort(a);
OUTPUT:
a[1] = "first";
a[2] = "last";
a[3] = "middle";
asort(src, dest)
: Funciona igual que la versión asort(a)
, sin embargo las modificaciones las realiza sobre el array dest
dejando intacto el array original src
:
asort(src, dest, how)
: Funciona igual que la versión asort(src, dest)
sin embargo el tercer argumento how
sirve para indicar la función con la cuál ordenar, a continuación se describen las funciones predefinidas de ordenamiento en awk:
Todas las versiones retornan el número de elementos dentro del array que se desea ordenar
Instrucción de awk que sirve para recorrer el array de forma transversal, es decir a través de esta instrucción se indica a awk la manera en la que se recorrerán de manera global los arrays
A continuación se describen todos los valores que puede tomar PROCINFO["sorted_in"]
:
@val_type_asc (* función default)
: Ordena los valores del array de acuero al tipo de dato del valor ( order ASC
)
@val_type_desc
: Ordena los valores del array de acuero al tipo de dato del valor ( order DESC
)
@val_str_asc
: Ordena los valores del array tratándolos como Strings
(order ASC
)
@val_str_desc
: Ordena los valores del array tratándolos como Strings
(order DESC
)
@val_num_asc
: Ordena los valores del array tratándolos como Integers
(order ASC
)
@val_num_desc
: Ordena los valores del array tratándolos como Integers
(order DESC
)
@ind_str_asc (* función default)
: Ordena los indices del array tratándolos como Strings
(order ASC
)
@ind_num_asc
: Ordena los indices del array tratándolos como Integers
( order ASC
)
@ind_str_desc
: Ordena los indices del array tratándolos como Strings
(order DESC
)
@ind_num_desc
: Ordena los indices del array tratándolos como Integers
( order DESC
)
Ejemplo:
BEGIN {
PROCINFO["sorted_in"]="@val_num_asc";
a["line 1"]="1";
a["line 10"]="10";
a["line 3"]="3";
for(key in a) {
print "a["key"]="a[key];
}
PROCINFO["sorted_in"]="@val_num_desc";
b["b-line 10"]="10";
b["b-line 100"]="100";
b["b-line 30"]="30";
for(key in b) {
print "b["key"]="b[key];
}
}
OUTPUTS:
a[line 1]=1
a[line 3]=3
a[line 10]=10
b[b-line 100]=100
b[b-line 30]=30
b[b-line 10]=10
Busca el texto [DEBUG] AbstractControlNode - [ENTER] onActionFromEdit
para el alias CIUDAD
(columna 8). Cuenta el número de ocurrencias al final y el conteo de los ids encontrados.
index($0, "[DEBUG] AbstractControlNode - [ENTER] onActionFromEdit") !=0 && $8 ~ "CIUDAD" \
{
f++;
printf "[%s] %s ",FILENAME,$0;
gsub("\"","",$0);
gsub(",","",$0);
if ($11 in map) {
val = map[$11];
map[$11] = val+1;
} else {
map[$11] = 1;
}
printf "ID_SURV_APPLIED("$11")("map[$11]")\n";
}
END {
print "FOUND=" f;
}
getline
: Pasa a la siguiente línea, cambiando el valor de $0
:
print $0 #imprime primer línea
getline
print $0 #imprime segunda línea
Retorno:
`getline' returns 1 if it finds a record, and 0 if the end of the
file is encountered. If there is some error in getting a record, such
as a file that cannot be opened, then `getline' returns -1
FNR
(file number record): Número de línea actual, awk resetea FNR
a cero cada que comienza el procesamiento de otro archivo (cuando se procesa más de un archivo al mismo tiempo).
NR
(number record): Número de líneas que ha procesado awk hasta el momento, este no se resetea cuando se procesa más de un archivo, continúa la cuenta cuando pasa al siguiente archivo.
FILENAME
: Nombre del archivo que se procesa actualmente
NF
(number fields): Número de columnas que tiene la fila actual
http://www.grymoire.com/Unix/AwkRef.html
https://www.tutorialspoint.com/awk/
: Ejemplos muy claros y cortos
https://www.shortcutfoo.com/blog/awk-by-example/
: Pocos ejemplos pero claros