Чтение строк из файла в массив Bash
Я пытаюсь прочитать файл, содержащий строки, в массив Bash.
Я пробовал следующее:
Attempt1
a=( $( cat /path/to/filename ) )
Attempt2
index=0
while read line ; do
MYARRAY[$index]="$line"
index=$(($index+1))
done < /path/to/filename
Обе попытки возвращают только один массив элементов, содержащий первую строку файла. Что я делаю не так?
Я бегу bash 4.1.5
Ответы
Ответ 1
Последняя версия на основе комментария Комментарий BinaryZebra
и здесь. Добавление command eval
позволяет удерживать выражение в текущей среде исполнения, а выражения before сохраняются только на протяжении eval.
Используйте $IFS, у которого нет пробелов \tabs, только символы новой строки /CR
$ IFS=$'\r\n' GLOBIGNORE='*' command eval 'XYZ=($(cat /etc/passwd))'
$ echo "${XYZ[5]}"
sync:x:5:0:sync:/sbin:/bin/sync
Также обратите внимание, что вы можете настроить массив просто отлично, но неправильно его прочитать - обязательно используйте как двойные кавычки ""
, так и скобки {}
, как в приведенном выше примере
Edit:
Обратите внимание на множество предупреждений о моем ответе в комментариях о возможном расширении glob, особенно gniourf-gniourf comments о моих предыдущих попытках обойти
Учитывая все эти предупреждения, я все еще оставляю этот ответ здесь (да, bash 4 уже много лет, но я помню, что некоторые маки только 2/3 года имеют pre-4 в качестве оболочки по умолчанию)
Другие примечания:
Можно также следовать приведенному ниже предложению drizzt и заменить раздвоенную подоболочку + cat с помощью
$(</etc/passwd)
Другая опция, которую я иногда использую, - это просто установить IFS в XIFS, а затем восстановить после. См. Также Sorpigal answer, который не нужно беспокоиться об этом
Ответ 2
Команда readarray
(также записанная как mapfile
) была введена в bash 4.0.
readarray a < /path/to/filename
Ответ 3
Самый простой способ прочитать каждую строку файла в массиве bash
:
IFS=$'\n' read -d '' -r -a lines < /etc/passwd
Теперь просто проиндексируйте массив lines
для извлечения каждой строки, например
printf "line 1: %s\n" "${lines[0]}"
printf "line 5: %s\n" "${lines[4]}"
# all lines
echo "${lines[@]}"
Ответ 4
Один альтернативный способ, если файл содержит строки без пробелов с 1-й строкой каждой строки:
fileItemString=$(cat filename |tr "\n" " ")
fileItemArray=($fileItemString)
Check:
Печать всего массива:
${fileItemArray[*]}
Length=${#fileItemArray[@]}
Ответ 5
Ваша первая попытка была близка. Вот простой подход, использующий вашу идею.
file="somefileondisk"
lines=`cat $file`
for line in $lines; do
echo "$line"
done
Ответ 6
#!/bin/bash
IFS=$'\n' read -d'' -r -a inlines < testinput
IFS=$'\n' read -d'' -r -a outlines < testoutput
counter=0
cat testinput | while read line;
do
echo "$((${inlines[$counter]}-${outlines[$counter]}))"
counter=$(($counter+1))
done
# OR Do like this
counter=0
readarray a < testinput
readarray b < testoutput
cat testinput | while read myline;
do
echo value is: $((${a[$counter]}-${b[$counter]}))
counter=$(($counter+1))
done