Bash: чтение строки файла, разделенной вкладкой, в массив


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

типичный пример bash "чтение файла по строке";

while read line
do
echo $line;
done < "myfile"

для меня, однако, myfile выглядит так (табуляция разделенных значений);

value1 value2 value3
value4 value5 value6

на каждой итерации цикла я бы хотел, чтобы каждая строка входила в массив, чтобы я мог

while read line into myArray
do
 echo myArray[0]
 echo myArray[1]
 echo myArray[2]
done < "myfile"

это будет печатать следующее На первом итерация цикла;

value1
value2
value3

затем на второй итерации он будет печатать

value4
value5
value6

это возможно? Единственный способ, который я вижу, это написать небольшую функцию, чтобы вырвать значения вручную, есть ли встроенная поддержка в bash для этого?

3   51  

3 ответа:

вы очень близки:

while IFS=$'\t' read -r -a myArray
do
 echo "${myArray[0]}"
 echo "${myArray[1]}"
 echo "${myArray[2]}"
done < myfile

(The -r говорит read это \ не является особенным во входных данных;-a myArray говорит ему разделить входную строку на слова и сохранить результаты в myArray; и IFS=$'\t' говорит, что он использует только вкладки для разделения слов, а не обычный bash по умолчанию также позволяет разделять слова пробелами. Обратите внимание, что этот подход будет относиться к одному или вкладки в качестве разделителя, поэтому, если какое-либо поле пусто, более поздние поля будут быть "сдвинутым" в более ранние позиции в массиве. Это нормально?)

если вы действительно хотите разделить каждое слово (значение bash) на другой индекс массива, полностью меняя массив в каждой итерации цикла while, ответ @ruakh является правильным подходом. Но вы можете использовать свойство read, чтобы разделить каждое прочитанное слово на разные переменные column1,column2,column3 как в этот код

while IFS=$'\t' read -r column1 column2 column3 ; do
  printf "%b\n" "column1<${column1}>"
  printf "%b\n" "column2<${column2}>"
  printf "%b\n" "column3<${column3}>"
done < "myfile"

чтобы достичь аналогичного результата, избегая доступа к индексу массива и улучшая читаемость кода, используя значимые имена переменных (конечно используя columnN это не очень хорошая идея, чтобы сделать это).

вы также можете попробовать,

OIFS=$IFS;
IFS="\t";

animals=`cat animals.txt`
animalArray=$animals;

for animal in $animalArray
do
    echo $animal
done

IFS=$OIFS;