array awk gawk

arrays in awk



¿Es posible agregar un elemento a una matriz en awk sin especificar un índice? (3)

Como han dicho otros, awk no proporciona ninguna funcionalidad como esta fuera de la caja. Su solución "hackish" puede funcionar para algunos conjuntos de datos, pero no para otros. Tenga en cuenta que podría agregar el mismo valor de matriz dos veces y desea que se represente dos veces dentro de la matriz.

$ echo 3 | awk ''BEGIN{ a[1]=5; a[2]=12; a[3]=2 } > { a[$1] = $1 } > END {print length(a) " - " a[3]}'' 3 - 3

La mejor solución puede ser informada por los datos que se encuentran en la matriz, pero aquí hay algunas ideas.

En primer lugar, si está seguro de que su índice siempre será numérico, siempre comenzará en 1, y que nunca borrará los elementos de la matriz, entonces la sugerencia de A[length(A)+1]="value" de triplee de A[length(A)+1]="value" puede funcionar para tú. Pero si elimina un elemento, entonces su próxima escritura puede sobrescribir su último elemento.

Si su índice no importa , y no le preocupa perder espacio con claves largas, puede usar un número aleatorio que sea lo suficientemente largo para reducir la probabilidad de colisiones. Una opción rápida y sucia podría ser:

srand() a[rand() rand() rand()]="value"

Recuerde usar srand() para una mejor aleatorización, y no confíe en rand() para producir números aleatorios reales. Esta es una solución menos que perfecta de varias maneras, pero tiene la ventaja de ser una sola línea de código.

Si sus teclas son numéricas pero posiblemente escasas , como en el ejemplo que rompería la solución de tripleee, puede agregar una pequeña búsqueda a su función de inserción:

function push (a, v, n) { n=length(a)+1 while (n in a) n++ a[n]=v }

El bucle while asegura que asignará un índice no utilizado. Esta función también es compatible con matrices que utilizan índices no numéricos: asigna teclas que son numéricas, pero no importa lo que ya esté allí.

Tenga en cuenta que awk no garantiza el orden de los elementos dentro de una matriz, por lo que la idea de que "empujará un elemento al final de la matriz" es incorrecta. Agregará este elemento a la matriz, pero no hay garantía de que aparezca por última vez cuando avance con un bucle for .

$ cat a #!/usr/bin/awk -f function push (a, v, n) { n=length(a)+1 while (n in a) n++ a[n]=v } { push(a, $0) } END { print "length=" length(a) for(i in a) print i " - " a[i] } $ printf ''3/nfour/ncinq/n'' | ./a length=3 2 - four 3 - cinq 1 - 3

Me doy cuenta de que awk tiene matrices asociativas, pero me pregunto si hay un awk equivalente a esto:

http://php.net/manual/en/function.array-push.php

La solución obvia es simplemente decir:

array[$new_element] = $new_element

Sin embargo, esto parece menos legible y más intrépido de lo que debe ser.


En gawk puedes encontrar la longitud de una matriz con la length(var) por lo que no es muy difícil cocinar tu propia función.

function push(A,B) { A[length(A)+1] = B }

Sin embargo, observe esta discusión: http://objectmix.com/awk/361598-gawk-length-array-question.html : todos los lugares a los que puedo acceder ahora tienen gawk 3.1.5, por lo que no puedo probar mi función correctamente. duh Pero aquí hay una aproximación.

vnix$ gawk ''# BEGIN: make sure arr is an array > BEGIN { delete arr[0] } > { print "=" length(arr); arr[length(arr)+1] = $1; > print length(arr), arr[length(arr)] } > END { print "---"; > for (i=1; i<=length(arr); ++i) print i, arr[i] }'' <<HERE > fnord foo > ick bar > baz quux > HERE =0 1 fnord =1 2 ick =2 3 baz --- 1 fnord 2 ick 3 baz


No creo que la longitud de un arreglo esté disponible de inmediato en awk (al menos no en las versiones con las que juego). Pero simplemente puedes mantener la longitud y luego hacer algo como esto:

array[arraylen++] = $0;

Y luego acceda a los elementos a través de los mismos valores enteros:

for ( i = 0; i < arraylen; i++ ) print array[i];