Si entendí esto bien, creo que básicamente quieres recorrer las listas de valores, y luego read
otra dentro del ciclo.
Aquí hay algunas opciones, 1 y 2 son probablemente las más sensatas.
1. Emular matrices con cadenas
Tener matrices 2D sería bueno, pero en realidad no es posible en Bash. Si sus valores no tienen espacios en blanco, una solución alternativa para aproximarse es pegar cada conjunto de tres números en una cadena y dividir las cadenas dentro del bucle:
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
Por supuesto, también podría usar algún otro separador, por ejemplo, for x in 1:2:3 ...
y IFS=: read a b c <<< "$x"
.
2. Reemplace la tubería con otra redirección para liberar stdin
Otra posibilidad es tener la read a b c
lectura de otro fd y dirigir la entrada a eso (esto debería funcionar en un shell estándar):
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
Y aquí también puede usar una sustitución de proceso si desea obtener los datos de un comando: while read a b c <&3; ...done 3< <(echo $'1 2 3\n4 5 6')
(la sustitución de proceso es una función bash / ksh / zsh)
3. Tome la entrada del usuario de stderr en su lugar
O, al revés, usando una tubería como en su ejemplo, pero tenga la entrada read
del usuario de stderr
(fd 2) en lugar de de stdin
dónde proviene la tubería:
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
Leer de stderr
es un poco extraño, pero en realidad a menudo funciona en una sesión interactiva. (También podría abrir explícitamente /dev/tty
, suponiendo que realmente desea omitir cualquier redirección, eso es lo que se less
usa para obtener la entrada del usuario incluso cuando los datos se canalizan a ella).
Aunque usarlo de stderr
esa manera podría no funcionar en todos los casos, y si está usando algún comando externo en lugar de read
, al menos necesitaría agregar un montón de redirecciones al comando.
Además, vea ¿Por qué mi variable es local en un bucle 'mientras se lee', pero no en otro bucle aparentemente similar? por algunos problemas relacionados ... | while
.
4. Corte partes de una matriz según sea necesario
Supongo que también podría aproximar una matriz 2D ish copiando secciones de una 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
También puede asignar ${a[0]}
etc. a a
, b
etc. si desea nombres para las variables, pero Zsh lo haría mucho mejor .
stderr
es un poco asqueroso, pero recuerdo que alguna utilidad lo hace. Pero todo lo que puedo encontrar ahora son los que solo uso/dev/tty
. Oh bien.<&2
(así como</dev/tty
) evita leer del stdin del script. Esto no va a funcionarprintf '682\n739' | ./script
. También tenga en cuenta queread -p
solo funciona en bash.while
bucle, por lo que realmente no puedes usar el stdin del script de todos modos ...read -u
también es bash, pero se puede reemplazar con redireccionamientos, y<<<
en el primero tampoco es estándar, pero es un poco más difícil de solucionar.Solo hay uno
/dev/stdin
,read
se leerá en cualquier lugar donde se use (por defecto).La solución es usar algún otro descriptor de archivo en lugar de 1 (
/dev/stdin
).Desde el código equivalente (en bash) hasta lo que publicaste [1] (mira abajo)
solo agrega
0</dev/tty
(por ejemplo) para leer desde el tty "real":En ejecución:
Otra alternativa es usar
0<&2
(que puede parecer extraño, pero es válido).Tenga en cuenta que la lectura de
/dev/tty
(también0<&2
) omitirá el stdin del script, esto no leerá los valores del eco:Otras soluciones
Lo que se necesita es redirigir una entrada a otro fd (descriptor de archivo).
Válido en ksh, bash y zsh:
O, con el ejecutivo:
Una solución que funciona en sh (
<<<
no funciona):Pero esto es probablemente más fácil de entender:
1 código más simple
Tu código es:
Un código simplificado (en bash) es:
Que, si se ejecuta, imprime:
Lo que solo muestra que la var d se está leyendo de la misma
/dev/stdin
.fuente
Con
zsh
, puedes escribirlo en su lugar:Para matrices 2D, vea también el
ksh93
shell:fuente