¿Cómo inicializar una matriz usando awk y bash?

¿Cómo inicializar una matriz usando awk y bash?

Estoy intentando almacenar valores de la primera línea de un archivo de texto en una matriz. Esto es lo que tengo hasta ahora:

arr_values=()

awk '
    NR==1 {
            for (i=0; i<=NF; i++)
               'arr_values[i]'=$i            #error here
          }' file.txt

for ((i=0; i<${#arr_values[@]}; i++))
do
   echo ${arr_values[i]}
done

Recibo un error al inicializar la matriz principalmente porque no sé cómo awkinicializar una matriz externa. ¿Alguna sugerencia (solo con awk)? Gracias.

Disculpa por el post cruzado, no obtuve la respuesta que quería.

Respuesta1

Es posible que obtenga mejores respuestas si explicara el contexto en cuanto apor qué awk... y cómo se ve la primera línea de datos.

Como no ha cambiado el separador de campos, supongo que está procesando una línea de elementos separados por espacios. Lo siguiente hará exactamente lo que estás buscando:

arr_values=()

read -ra arr_values <<< $(head -n 1 file.txt)

for s in "${arr_values[@]}"; do
    echo "$s"
done

Todo el trabajo se realiza en el readcomando. A menos que necesite procesar los valores de una matriz varias veces; entonces, simplemente podrías hacer:

set -f    # disable globbing, in case the lines contain wildcard characters
for s in $(head -n 1 file.txt); do
    set +f
    echo "$s"
done
set +f

Esto colocará cada entrada de campo que no esté en blanco y que esté separada por espacios en blanco $sy realizará una pasada a través del bucle.

Respuesta2

No puedes hacerlo precisamente de esta manera. Debe dejar que se ejecute el comando awk, creando una serie de valores de salida delimitados por algún delimitador (espacio, tabulación, NUL o algo así), luego asignarlos a los elementos de la matriz. La razón de esto es que awk es un programa que se ejecuta mediante el shell y se ejecuta hasta su finalización antes decualquierse ejecutan más operaciones de shell. No puedes incrustar cosas de shell en tus cosas awk como esta.

Puede hacer algo como lo siguiente para usar su ejemplo simple, pero no estoy seguro de que el código awk que proporcionó haga lo que desea en cualquier caso. Si un archivo tiene cero registros o más de un registro, la salida (y, por tanto, la matriz del shell) contendrá las líneas del archivo. Parece que desea que la matriz de salida contenga un conjunto de números enteros desde cero hasta la cantidad de campos que encuentre en un archivo si, y solo, si contiene solo un registro. Si desea evitar que aparezcan archivos más grandes en la matriz, deberá agregar una segunda acción sin patrón en el código awk que contenga solo "{ }" como acción, como lo hice a continuación. Además, desactive la expansión de comodines del nombre de archivo ( set -f) en caso de que la línea contenga caracteres comodín \[*?.

set -f
arr_values=(`awk '
    NR==1 {
            for (i=0; i<=NF; i++)
               print $i
          }

          { }' file.txt`)
set +f
for ((i=0; i<${#arr_values[@]}; i++))
do
   echo "${arr_values[i]}"
done

Respuesta3

Si quieres usar awk, puedes hacerlo así:

arr_values=( $(awk '{print;exit}' file) )

El shell hará la división en espacios en blanco. Tenga en cuenta que si la línea contiene comodines, se expandirán a la lista de archivos coincidentes (si los hay). Úselo set -fpara deshabilitar la expansión de comodines.

set -f
arr_values=( $(awk '{print;exit}' file) )
set +f

Respuesta4

No sé sobre las otras cosas, pero si estás dividiendo en espacios en blanco, esto almacenará la primera línea de un archivo de texto en la matriz de shell dividida en espacios en blanco:

set -f ; set -- $(head -n1 <textfile) ; set +f

Eso es todo lo que se necesita. Ahora sus parámetros posicionales son los distintos índices de la matriz y su matriz es "$@".

información relacionada