Как я могу прочитать пользовательский ввод как массив в Bash?


15

Как я могу прочитать пользовательский ввод как массив в bashоболочке?


Я предполагаю, что вы хотите читать со стандартного ввода? Мой ответ также будет работать с исполнением, как cat war_and_peace.txt | ./array_test.sh.
Стефано Палаццо

Или просто ./array_test.sh < war_and_peace.txt.
Элия ​​Каган,

Ответы:


14

Вот один из способов сделать это:

while read line
do
    my_array=("${my_array[@]}" $line)
done

echo ${my_array[@]}

Если вы просто запустите его, он будет продолжать читать со стандартного ввода, пока вы не нажмете Ctrl + D (EOF). После этого введенные вами строки будутmy_array . Некоторые могут найти этот код запутанным. Тело цикла в основном говорит my_array = my_array + element.

Несколько интересных частей документации:


3
read -rиногда очень полезно / важно ... Ссылка Стефано на «прочитанную встроенную страницу руководства» объясняет его назначение ... (чтобы предотвратить интерпретацию обратной косой черты).
Peter.O

10

Прочитайте это, используя это:

read -a arr

А для печати используйте:

for elem in ${arr[@]}
do 
  echo $elem
done

4

И тот, который не воссоздает массив каждый раз (хотя требует bash 3.1 или новее):

array=()
while IFS= read -r -p "Next item (end with an empty line): " line; do
    [[ $line ]] || break  # break if line is empty
    array+=("$line")
done

printf '%s\n' "Items read:"
printf '  «%s»\n' "${array[@]}"

Смотрите http://mywiki.wooledge.org/BashFAQ/001 для получения дополнительной информации.

И как всегда, чтобы избежать написания ошибок, прочитайте http://mywiki.wooledge.org/BashGuide и избегайте руководств tldp, таких как Руководство по написанию сценариев Advanced bash.


Хорошие ссылки ... Спасибо за указание на IFSпроблему. Не обнуляя его, «читайте» все начальные и конечные пробелы ... и, конечно, -rтоже ...
Peter.O

0

Как насчет этого однострочника;)

arr=( $(cat -) )
echo ${arr[@]}

Редактировать:

В bash,

arr=(val1 val2 ...)

это способ присвоения массива . Используя его в сочетании с подстановкой команд, вы можете читать массивы из конвейера, которые невозможно использовать readдля прямой реализации этого:

echo -e "a\nb" | read -a arr
echo ${arr[@]}

Вы обнаружите, что он ничего не выводит из-за того, что readон ничего не делает, когда stdinявляется конвейером, поскольку конвейер может быть запущен в подоболочке, так что переменная может вообще не использоваться.

Используя способ, предложенный этим ответом:

arr=(`echo -e "a\nb"`)
echo ${arr[@]}

Это a bнамного проще и понятнее, чем любой обходной путь, заданный ответами чтения значений в переменную оболочки из канала и при чтении в bash после того, как канал не устанавливает значения .


ты проверял это?
cmak.fr

@ cmak.fr да, это работает для меня
Quark

@Melebius Я приложил объяснение этого и преимущества этого однострочника.
ЦзяХао Сюй
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.