Как инициализировать массив с помощью awk и bash?

Как инициализировать массив с помощью awk и bash?

Я пытаюсь сохранить значения первой строки текстового файла в массив. Вот что у меня получилось:

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

Я получаю ошибку при инициализации массива, в основном потому, что не знаю, как использовать awkдля инициализации внешнего массива. Есть предложения (только с awk)? Спасибо.

Извините за перекрестный пост, я не получил желаемого ответа.

решение1

Вы можете получить лучшие ответы, если объясните контекст.почему awk... и как выглядит первая строка данных.

Поскольку вы не изменили разделитель полей, я предполагаю, что вы обрабатываете строку элементов, разделенных пробелами. Следующий код сделает именно то, что вы ищете:

arr_values=()

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

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

Вся работа выполняется в readкоманде. Если только вам не нужно обрабатывать значения в массиве несколько раз, то вы можете просто сделать:

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

Это поместит каждую непустую запись поля, разделенную пробелами, в $sи выполнит один проход по циклу.

решение2

Вы не можете сделать это именно так. Вы должны позволить команде awk выполниться, создав ряд выходных значений, разделенных каким-либо разделителем (пробелом, табуляцией, NUL или чем-то еще), а затем присвоить их элементам массива. Причина этого в том, что awk — это программа, которая запускается оболочкой и выполняется до завершения перед тем, каклюбойбольше операций оболочки выполняются. Вы не можете встроить вещи оболочки в ваши вещи awk таким образом.

Вы можете сделать что-то вроде нижеприведенного, чтобы использовать ваш простой пример, но я не уверен, что предоставленный вами код awk в любом случае сделает то, что вам нужно. Если файл содержит ноль записей или более одной записи, вывод (и, таким образом, массив оболочки) будет содержать строки файла. Похоже, вы хотите, чтобы выходной массив содержал набор целых чисел от нуля до количества полей, которые вы найдете в файле, если-и-только-если он содержит только одну запись. Если вы хотите избежать отображения больших файлов в массиве, вам придется добавить второе действие без шаблона в код awk, содержащее только "{ }" в качестве действия, как я сделал ниже. Также отключите расширение подстановочных знаков имени файла ( set -f) в случае, если строка содержит подстановочные знаки \[*?.

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

решение3

Если вы хотите использовать awk, вы можете сделать так:

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

Оболочка выполнит разбиение по пробелам. Обратите внимание, что если строка содержит подстановочные знаки, они будут расширены до списка соответствующих файлов (если таковые имеются). Используйте set -fдля отключения расширения подстановочных знаков.

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

решение4

Я не знаю, как обстоят дела с остальными вещами, но если вы разбиваете данные по пробелам, то это сохранит первую строку текстового файла в массиве оболочки, разбитом по пробелам:

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

Это все, что нужно. Теперь ваши позиционные параметры — это различные индексы массива, а ваш массив — это "$@".

Связанный контент