Se eu entendi direito, acho que você deseja basicamente fazer um loop sobre listas de valores e depois read
outro dentro do loop.
Aqui estão algumas opções: 1 e 2 são provavelmente as mais saudáveis.
1. Emule matrizes com strings
Ter matrizes 2D seria bom, mas não é realmente possível no Bash. Se seus valores não tiverem espaço em branco, uma solução alternativa para aproximar isso é colar cada conjunto de três números em uma sequência e dividir as seqüências dentro do loop:
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
Claro que você também pode usar outro separador, por exemplo, for x in 1:2:3 ...
e IFS=: read a b c <<< "$x"
.
2. Substitua o tubo por outro redirecionamento para liberar stdin
Outra possibilidade é ter a read a b c
leitura de outro fd e direcionar a entrada para isso (isso deve funcionar em um shell padrão):
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
E aqui você também pode usar uma substituição de processo se desejar obter os dados de um comando: while read a b c <&3; ...done 3< <(echo $'1 2 3\n4 5 6')
(a substituição do processo é um recurso bash / ksh / zsh)
3. Aceite a entrada do usuário do stderr
Ou, ao contrário, utilizando um tubo como no seu exemplo, mas têm a entrada do usuário read
de stderr
(FD 2) em vez de stdin
onde o tubo vem:
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
Ler stderr
é um pouco estranho, mas na verdade geralmente funciona em uma sessão interativa. (Você também pode abrir explicitamente /dev/tty
, supondo que você realmente queira ignorar qualquer redirecionamento, é isso que as coisas less
usam para obter a entrada do usuário, mesmo quando os dados são canalizados para ele.)
Embora o uso stderr
desse tipo possa não funcionar em todos os casos, e se você estiver usando algum comando externo em vez de read
, pelo menos, precisará adicionar vários redirecionamentos ao comando.
Além disso, consulte Por que minha variável local é em um loop 'while read', mas não em outro loop aparentemente semelhante? para algumas questões relacionadas ... | while
.
4. Corte partes de uma matriz, conforme necessário
Suponho que você também possa aproximar uma matriz 2D-ish copiando fatias de uma matriz unidimensional regular:
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
Você também pode atribuir ${a[0]}
etc. a a
, b
etc , se quiser nomes para as variáveis, mas o Zsh faria isso muito mais bem .