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 .
stderr
assim é um pouco nojento, mas tive a lembrança de que algum utilitário faz isso. Mas tudo o que posso encontrar agora são aqueles que apenas usamos/dev/tty
. Ah bem.<&2
(e também</dev/tty
) evitar a leitura do stdin do script. Isso não vai funcionarprintf '682\n739' | ./script
. Observe também queread -p
só funciona no bash.while
canal do eco para esse loop, então você realmente não pode usar o stdin do script de qualquer maneira ...read -u
também é bash, mas pode ser substituído por redirecionamentos, e<<<
em o primeiro também não é padrão, mas é um pouco mais difícil de contornar.Existe apenas um
/dev/stdin
,read
irá ler a partir dele em qualquer lugar em que for usado (por padrão).A solução é usar outro descritor de arquivo em vez de 1 (
/dev/stdin
).Do código equivalente (no bash) ao que você postou [1] (veja abaixo),
basta adicionar
0</dev/tty
(por exemplo) para ler o tty "real":Na execução:
Outra alternativa é usar
0<&2
(o que pode parecer estranho, mas é válido).Observe que a leitura de
/dev/tty
(também0<&2
) ignorará o stdin do script, isso não lerá os valores do eco:Outras soluções
O que é necessário é redirecionar uma entrada para outra fd (descritor de arquivo).
Válido em ksh, bash e zsh:
Ou, com exec:
Uma solução que funciona em sh (
<<<
não funciona):Mas isso é provavelmente mais fácil de entender:
1 código mais simples
Seu código é:
Um código simplificado (no bash) é:
Que, se executado, imprime:
O que está apenas mostrando que o var d está sendo lido do mesmo
/dev/stdin
.fonte
Com
zsh
, você pode escrevê-lo:Para matrizes 2D, veja também o
ksh93
shell:fonte