Чтение значений массива в качестве пользовательского ввода дает неправильную длину массива и только -a или -p работает при чтении

Проблема 1: Я хочу получить элементы массива в качестве пользовательских входов во время выполнения; распечатать элементы и напечатать длину массива. Это то, что у меня есть:

read -a myarray echo "array items" ${myarray[@]} echo "array length" ${#myarray[@]} 

Во время выполнения я дал в качестве входных данных следующее:

 $ ("apple fruit" "orange" "grapes") 

Выход был,

 array items "apple fruit" "orange" "grapes" array length 4 

что неверно.

Если я не прошу ввода пользователя и вместо этого использовал массив, объявленный и инициализированный как часть кода как myarray=("apple fruit" "orange" "grapes") длина массива отражается как 3. Итак, похоже мое использование команды чтения неверно.

Проблема 2: Если я добавлю команду командной строке в следующую команду,

 read -p "enter array items: " myarray 

первый элемент «яблочный плод» печатается как плод », а длина также неверна.

Если я удалю приглашение и добавлю -a, все будет хорошо. Если я совмещаю как a, так и p и передаю их как read -ap, приглашение вообще не всплывает. Он ожидает значений без какого-либо сообщения. Почему это так? Может кто-нибудь объяснить мне, что не так?

3 Solutions collect form web for “Чтение значений массива в качестве пользовательского ввода дает неправильную длину массива и только -a или -p работает при чтении”

Задача 1:

В вашем примере read не получает свой вход из аргумента командной строки, а из stdin. Таким образом, вход, который он получает, не проходит через синтаксический анализатор строки bash . Вместо этого он рассматривается как буквальная строка, ограниченная пробелами. Таким образом, с вашим вводом ваши значения массива становятся:

 [0]->("apple [1]->fruit" [2]->"orange" [3]->"grapes" 

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

 apple\ fruit oranges grapes 

Задача 2: для read для хранения ввода, который он получает как массив, у вас должен быть ключ -a за которым следует имя массива. Поэтому вам нужно:

 read -a myarray -p "Enter your items" 

Анализатор командной строки оболочки заботится о двойных и одинарных кавычках, но read не делает (таким образом, оно также не удаляет их). Для read ввода нужны обратные косые черты:

 apple\ fruit orange grapes 

Если вы хотите, чтобы пользователь использовал кавычки оболочки для разграничения элементов (и не только backslash ), в zsh вы могли бы сделать:

 IFS= read -r 'string?Please enter the elements: ' array=("${(@XQ)${(z)string}}") 
  • (z) состоит в том, чтобы разбить $string на такие элементы, как это сделал бы синтаксический анализатор оболочки.
  • Q чтобы удалить один уровень цитирования из полученных слов
  • X для сообщения об ошибках в синтаксисе
  • @ и цитаты для сохранения пустых элементов.

Таким образом, пользователь может вводить такие вещи, как:

 'first word' "second word" third\ word $'word\nwith\nnewline' '' 

Помните, что, хотя расширение не выполняется, синтаксис ожидаемого кода оболочки не ограничивается цитированием. Например, $(foo bar) будет разбираться в одно слово $(foo bar) , ${unclosed приведет к синтаксической ошибке. Пользователь должен будет ввести их как '$(foo)' 'bar)' или “ $ {unclosed '.

  • Извлечь имя файла из другого имени файла.
  • получить первый аргумент CLI после опций в shell scipt
  • Считайте и объедините последовательные паттерны
  • Перенаправить ввод в несколько разных файлов вывода
  • Как убить процесс, запущенный как демон?
  • Скрипты многотомных (GNU) `tar` с заранее определенным количеством томов
  • Установите выравнивание числовых столбцов при разделении данных
  • Улучшение производительности скрипта
  • Запустить фоновый процесс из sh и закрыть терминал
  • sudo kill: операция не разрешена через SSH
  • оценка команд двойной блокировки в выражении состояния bash
  • Linux и Unix - лучшая ОС в мире.