Como inicializar um array usando awk e bash?

Como inicializar um array usando awk e bash?

Estou tentando armazenar valores da primeira linha de um arquivo de texto em uma matriz. Aqui está o que tenho até agora:

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

Estou recebendo um erro ao inicializar o array principalmente porque não sei como usá-lo awkpara inicializar um array externo. Alguma sugestão (apenas com awk)? Obrigado.

Peço desculpas pela postagem cruzada, não obtive a resposta que queria.

Responder1

Você pode obter respostas melhores se explicar o contextopor que awk... e a aparência da primeira linha de dados.

Como você não alterou o separador de campos, presumo que você esteja processando uma linha de itens separados por espaços. O seguinte fará exatamente o que você está procurando:

arr_values=()

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

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

Todo o trabalho é feito no readcomando. A menos que você precise processar os valores em uma matriz várias vezes; então, você poderia simplesmente fazer:

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

Isso colocará cada entrada de campo não em branco separada por espaços em branco $se fará uma passagem pelo loop.

Responder2

Você não pode fazer isso exatamente dessa maneira. Você deve deixar o comando awk ser executado, criando uma série de valores de saída delimitados por algum delimitador (espaço, tabulação, NUL ou algo assim) e, em seguida, atribuí-los aos elementos do array. A razão para isso é que awk é um programa executado pelo shell e executado até a conclusão antesqualquermais operações de shell são executadas. Você não pode incorporar coisas do shell em suas coisas do awk assim.

Você pode fazer algo como abaixo para usar seu exemplo simples, mas não tenho certeza se o código awk que você forneceu fará o que você deseja em qualquer caso. Se um arquivo tiver zero registros ou mais de um registro, a saída (e, portanto, o array shell) conterá as linhas do arquivo. Parece que você deseja que a matriz de saída contenha um conjunto de números inteiros de zero até o número de campos encontrados em um arquivo se e somente se ele contiver apenas um registro. Se você deseja evitar que arquivos maiores apareçam no array, você terá que adicionar uma segunda ação sem padrão no código awk contendo apenas "{}" como a ação que fiz abaixo. Além disso, desative a expansão do curinga do nome do arquivo ( set -f) caso a linha contenha caracteres curinga \[*?.

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

Responder3

Se quiser usar awk, você pode fazer assim:

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

O shell fará a divisão nos espaços em branco. Observe que se a linha contiver curingas, eles serão expandidos para a lista de arquivos correspondentes (se houver). Use set -fpara desativar a expansão curinga.

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

Responder4

Não sei sobre as outras coisas, mas se você estiver dividindo em espaço em branco, isso armazenará a primeira linha de um arquivo de texto na matriz de shell dividida em espaço em branco:

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

Isso é tudo que é preciso. Agora, seus parâmetros posicionais são os vários índices do array e seu array é "$@".

informação relacionada