Se eu acertei, acho que você deseja fazer um loop sobre as listas de valores e, em seguida, read
another dentro do loop.
Aqui estão algumas opções, 1 e 2 são provavelmente as mais saudáveis.
1. Emular matrizes com strings
Ter arrays 2D seria bom, mas não é realmente possível no Bash. Se seus valores não tiverem espaços em branco, uma solução alternativa para aproximar isso é inserir cada conjunto de três números em uma string e dividir as strings 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 pipe por outro redirecionamento para liberar stdin
Outra possibilidade é ter o read a b c
lido 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 quiser 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. Tome a entrada do usuário de stderr em vez disso
Ou, ao contrário, usando um pipe como no seu exemplo, mas peça ao usuário que insira read
de stderr
(fd 2) em vez de stdin
de onde o duto 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
A leitura de stderr
é um pouco estranha, mas na verdade funciona frequentemente em uma sessão interativa. (Também é possível abrir explicitamente /dev/tty
, supondo que você queira realmente ignorar qualquer redirecionamento, é isso que o material less
usa para obter a entrada do usuário mesmo quando os dados são canalizados para ele.)
Embora usar stderr
como esse pode não funcionar em todos os casos, e se você estiver usando algum comando externo em vez de read
, precisará pelo menos adicionar vários redirecionamentos ao comando.
Além disso, veja Por que minha variável local está em um loop 'while read', mas não em outro loop aparentemente similar? para algumas questões relativas a ... | while
.
4. Cortar partes de uma matriz conforme necessário
Suponho que você também possa aproximar uma matriz 2D-ish copiando fatias de uma unidimensional normal:
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 Zsh faria isso muito mais bem .