2010-06-17 33 views
13

Awk ofrece indexación asociativa para el procesamiento de matriz. Los elementos de la matriz 1 dimensional se pueden repetir:iteración de matriz Awk para matrices multidimensionales

por ej.

for(index in arr1) 
    print "arr1[" index "]=" arr1[index] 

¿Pero cómo se hace esto para una matriz bidimensional? ¿Tiene algún tipo de sintaxis, dada a continuación, el trabajo?

for(index1 in arr2) 
for(index2 in arr2) 
    arr2[index1,index2]  
+0

'gawk' a partir de v4 admite matrices como elementos, es decir, matrices anidadas, más flexibles que las matrices multidimensionales,' para (i en arr2) para (j en arr2 [i]) imprimir arr2 [i] [j] ', ver [Respuesta de JJoao] (http://stackoverflow.com/a/35891319/1290731) – jthill

Respuesta

29

AWK falsifica matrices multidimensionales al concatenar los índices con el carácter de la variable SUBSEP (0x1c). Se puede recorrer una matriz de dos dimensiones utilizando split como esto (en base a un ejemplo en el archivo info gawk):

awk 'BEGIN { OFS=","; array[1,2]=3; array[2,3]=5; array[3,4]=8; 
    for (comb in array) {split(comb,sep,SUBSEP); 
    print sep[1], sep[2], array[sep[1],sep[2]]}}' 

Salida:

2,3,5 
3,4,8 
1,2,3 

Puede, sin embargo, repetir un indexado numéricamente matriz mediante anidada para bucles:

for (i = 1; i <= width; i++) 
    for (j = 1; j < = height; j++) 
     print array[i, j] 

Otro poco notable de información de la GAWK manual:

Para comprobar si existe una secuencia de índice particular en una matriz multidimensional, utilice el mismo operador (en) que se utiliza para las matrices de dimensión única. Escribir toda la secuencia de índices entre paréntesis, separados por comas, como el operando de la izquierda:

 (subscript1, subscript2, ...) in array 
5

No, la sintaxis

for(index1 in arr2) for(index2 in arr2) { 
    print arr2[index1][index2]; 
} 

no va a funcionar. Awk realmente no admite matrices multidimensionales. Lo que hace, si haces algo como

x[1,2] = 5; 

es concatenar los dos índices (1 & 2) para hacer una cadena, separados por el valor de la variable SUBSEP. Si esto es igual a "*", entonces tendría el mismo efecto que

x["1*2"] = 5; 

El valor por defecto de SUBSEP es un personaje que no se imprime, lo que corresponde a Ctrl + \. Se puede ver esto con la siguiente secuencia de comandos:

BEGIN { 
    x[1,2]=5; 
    x[2,4]=7; 
    for (ix in x) { 
     print ix; 
    } 
} 

La ejecución de este da:

% awk -f scriptfile | cat -v 
1^\2 
2^\4 

Así, en respuesta a su pregunta - la forma de repetición de una matriz multidimensional - sólo tiene que utilizar un solo bucle for(a in b) , pero es posible que necesite un trabajo adicional para dividir a en sus x y y partes.

3

Las versiones actuales de gawk (el awk GNU, por defecto en Linux, y la posibilidad de instalar todos lados querer), tiene matrices reales multidimensionales.

for(b in a) 
    for(c in a[b]) 
     print a[b][c], c , b 

véase también la función isarray()

1

voy a dar un ejemplo de cómo utilizar esto en mis datos de consulta de procesamiento de trabajo. Suponga que tiene un archivo de extracción completa de las transacciones por categoría de producto y la identificación del cliente:

customer_id category sales 
1111   parts  100.01 
1212   parts  5.20 
2211   screws  1.33 
...etc... 

Es fácil de usar awk para contar los clientes distintos en total con una compra:

awk 'NR>1 {a[$1]++} END {for (i in a) total++; print "customers: " total}' \ 
datafile.txt 

Sin embargo, el cálculo del número de clientes distintos con una compra en cada categoría sugiere una matriz bidimensional:

awk 'NR>1 {a[$2,$1]++} 
     END {for (i in a) {split(i,arr,SUBSEP); custs[arr[1]]++} 
      for (k in custs) printf "category: %s customers:%d\n", k, custs[k]}' \ 
datafile.txt 

El incremento de custs[arr[1]]++ obras porque cada categoría/custo mer_id pair es único como índice de la matriz asociativa utilizada por awk.

En verdad, yo uso gnu awk que es más rápido y puedo hacer array[i][j] como lo mencionó D. Williamson. Pero quería asegurarme de poder hacer esto en awk estándar.

1

awk (1) fue diseñado originalmente - en parte - para ser una herramienta de enseñanza para el lenguaje C, y las matrices multidimensionales han estado tanto en C como en awk (1) prácticamente para siempre. como tal, POSIX IEEE 1003.2 los estandarizó.

Para explorar la sintaxis y la semántica, si se crea el siguiente archivo llamado "test.awk":

BEGIN { 
    KEY["a"]="a"; 
    KEY["b"]="b"; 
    KEY["c"]="c"; 
    MULTI["a"]["test_a"]="date a"; 
    MULTI["b"]["test_b"]="dbte b"; 
    MULTI["c"]["test_c"]="dcte c"; 
} 
END { 
    for(k in KEY) { 
    kk="test_" k ; 
    print MULTI[k][kk] 
    } 
    for(q in MULTI) { 
    print q 
    } 
    for(p in MULTI) { 
    for(pp in MULTI[p]) { 
     print MULTI[p][pp] 
    } 
    } 
} 

y ejecutarlo con este comando:

awk -f test.awk /dev/null 

le aparecerá el siguiente salida:

date a 
dbte b 
dcte c 
a 
b 
c 
date a 
dbte b 
dcte c 

al menos en Linux Mint 18 Cinnamon 64 bits 4.4.0-21-genérico # 37-Ubuntu SMP

Cuestiones relacionadas