Como inicializar um array usando awk e bash?

2

Estou tentando armazenar valores da primeira linha de um arquivo de texto em uma matriz. Aqui está o que eu 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 usar awk para inicializar um array externo. Alguma sugestão (apenas com awk )? Obrigado.

Peça desculpas pelo post, não recebi a resposta que queria.

    
por Alias 23.06.2014 / 17:49

4 respostas

2

Você pode obter respostas melhores se explicar o contexto para por que awk ... e como é a primeira linha de dados.

Como você não alterou o separador de campo, suponho que 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 comando read . A menos que você tenha a necessidade de 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 vazia separada por espaços em branco em $s e fará uma passagem pelo loop.

    
por 23.06.2014 / 19:24
2

Você não pode fazer isso exatamente assim. Você tem que deixar o comando awk executar, criando uma série de valores de saída delimitados por algum delimitador (espaço, tabulação, NUL ou algo assim), então atribua-os aos elementos da matriz. A razão para isto é que o awk é um programa que é executado pelo shell e é executado até a conclusão antes de qualquer mais operações do shell serem executadas. Você não pode incorporar coisas de shell em coisas estranhas como esta.

Você pode fazer algo parecido com o abaixo para usar o seu exemplo simples, mas não tenho certeza se o código do 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, a matriz de 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 para o número de campos que você encontra em um arquivo if-and-only - 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 eu fiz abaixo. Além disso, desative a expansão do curinga de nome de 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
    
por 23.06.2014 / 18:24
2

Se você quiser usar awk , você pode fazer assim:

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

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

set -f
arr_values=( $(awk '{print;exit}' file) )
set +f
    
por 23.06.2014 / 18:03
0

Eu 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 o que é preciso. Agora seus parâmetros posicionais são os vários índices da matriz e sua matriz é "$@" .

    
por 23.06.2014 / 17:58