Читать разделенную табуляцией строку файла в массив
Я хотел бы прочитать файл в сценарий, строка за строкой. Каждая строка в файле состоит из нескольких значений, разделенных вкладкой, я хотел бы прочитать каждую строку в массив.
Типичный пример 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 встроенная поддержка для этого?
Ответы
Ответ 1
Вы очень близки:
while IFS=$'\t' read -r -a myArray
do
echo "${myArray[0]}"
echo "${myArray[1]}"
echo "${myArray[2]}"
done < myfile
(-r
сообщает read
, что \
не является специальным во входных данных, -a myArray
сообщает ему разбить строку ввода на слова и сохранить результаты в myArray
, а IFS=$'\t'
указывает, что он использует только вкладки для разделения слов вместо обычного стандартного значения Bash, также позволяя пробелам также разделить слова. Обратите внимание, что этот подход будет обрабатывать одну или несколько вкладок в качестве разделителя, поэтому, если какое-либо поле пустые, более поздние поля будут "сдвинуты" на более ранние позиции в массиве. Это нормально?)
Ответ 2
Если вы действительно хотите разбить каждое слово (bash значение) на другой индекс массива, полностью изменяющий массив в каждой итерации цикла while, правильный ответ. Но вы можете использовать свойство 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
не рекомендуется делать).
Ответ 3
Вы также можете попробовать,
OIFS=$IFS;
IFS="\t";
animals=`cat animals.txt`
animalArray=$animals;
for animal in $animalArray
do
echo $animal
done
IFS=$OIFS;