true - bash: lectura interactiva anidada dentro de un bucle que también usa lectura
while read line bash (2)
Como ya está leyendo todo el archivo en la memoria, léalo en una matriz en lugar de una sola cadena.
# Requires bash 4 or later
mapfile -t loop_input < $HOME/.get_iplayer/tv.cache
for line in "${loop_input[@]}"; do
print_show "$line"
read -n 1 -p "do stuff? [y/n] : " resp
done
Si todavía usas una versión anterior de bash, aún así recomiendo leer el archivo en una matriz en lugar de una sola cadena, pero es menos conveniente.
declare -a loop_input
while read; do loop_input+=("$REPLY"); done
for line in "${loop_input[@]}"; do
...
done
o, simplemente no puede leer todo el archivo en la memoria:
while read -u 3 line; do
....
done 3< $HOME/.get_iplayer/tv.cache
¿Cómo codifica una respuesta interactiva en este ciclo while?
#!/bin/bash
shows=$(< ${HOME}/.get_iplayer/tv.cache)
# ...
# ... stuff with shows omitted ...
# ...
function print_show {
# ...
return
}
while read -r line
do
print_show "$line"
read -n 1 -p "do stuff? [y/n] : " resp # PROBLEM
# ...
# resp actions omitted
# ...
done <<< "$shows"
Entonces, un archivo se lee, se "procesa" y luego los datos orientados a la línea resultantes se utilizan en un ciclo de while read
simultánea.
Pero la línea de lectura dentro del ciclo while no funciona como se esperaba, es decir, no espera la respuesta del usuario, presumiblemente debido al contexto de while read
que está encapsulado.
¿Podría sugerirnos cómo solucionar esto o un mecanismo alternativo?
Has identificado correctamente que la causa es que dentro del
while ...; do ...; done <<< "$shows"
loop, stdin ha sido redirigido, por lo tanto, read
ya no se lee desde el teclado.
Puede resolver esto utilizando un descriptor de archivo distinto de 0; por ejemplo,
while read -r -u 3 line; do ...; done 3<${HOME}/.get_iplayer/tv.cache
usará FD 3 para el archivo en lugar de FD 0, permitiendo que la read
normal (sin -u
) use stdin original, o
while ...; do read -n 1 -p "do stuff? [y/n] : " -u 3 resp; done 3<&0 <<< "$shows"
para clonar el FD 0 original a FD 3 antes de reemplazar el FD 0 con su cuerda.