Если я понял это правильно, я думаю, что вы хотите в основном перебирать списки значений, а затем read
еще один в цикле.
Вот несколько вариантов, 1 и 2, вероятно, самые разумные.
1. Эмулируйте массивы со строками
Было бы неплохо иметь двумерные массивы, но в Bash это невозможно. Если ваши значения не имеют пробелов, используйте один обходной путь, то есть вставьте каждый набор из трех чисел в строку и разбейте строки внутри цикла:
for x in "1 2 3" "4 5 6"; do
read a b c <<< "$x";
read -p "Enter a number: " d
echo "$a - $b - $c - $d ";
done
Конечно, вы можете использовать и другой разделитель, например, for x in 1:2:3 ...
и IFS=: read a b c <<< "$x"
.
2. Замените канал другим перенаправлением, чтобы освободить стандартный ввод.
Другой возможностью является read a b c
чтение с другого fd и направление ввода на него (это должно работать в стандартной оболочке):
while read a b c <&3; do
printf "Enter a number: "
read d
echo "$a - $b - $c - $d ";
done 3<<EOF
1 2 3
4 5 6
EOF
И здесь вы также можете использовать подстановку процесса, если вы хотите получить данные из команды: while read a b c <&3; ...done 3< <(echo $'1 2 3\n4 5 6')
(подстановка процесса - это функция bash / ksh / zsh)
3. Взять пользовательский ввод вместо stderr
Или, наоборот, используя канал, как в вашем примере, но используйте пользовательский ввод read
из stderr
(fd 2) вместо того, stdin
откуда пришел канал:
echo $'1 2 3\n4 5 6' |
while read a b c; do
read -u 2 -p "Enter a number: " d
echo "$a - $b - $c - $d ";
done
Чтение из stderr
немного странно, но на самом деле часто работает в интерактивном сеансе. (Вы также можете явно открыть /dev/tty
, предполагая, что вы хотите фактически обойти любые перенаправления, вот что вроде как less
использует для получения ввода пользователя, даже когда данные передаются на него.)
Хотя stderr
такое использование может работать не во всех случаях, и если вместо него вы используете какую-то внешнюю команду read
, вам, по крайней мере, нужно добавить в команду несколько перенаправлений.
Кроме того, см. Почему моя переменная локальна в одном цикле «пока читается», а не в другом, казалось бы, похожем цикле? для некоторых вопросов, касающихся ... | while
.
4. Нарезать части массива по мере необходимости
Я полагаю, вы также можете аппроксимировать двумерный массив, копируя срезы обычного одномерного:
data=(1 2 3
4 5 6)
n=3
for ((i=0; i < "${#data[@]}"; i += n)); do
a=( "${data[@]:i:n}" )
read -p "Enter a number: " d
echo "${a[0]} - ${a[1]} - ${a[2]} - $d "
done
Вы также можете назначить ${a[0]}
и т. Д. a
, И b
т. Д., Если вы хотите имена для переменных, но Zsh сделает это намного лучше .