我正在尝试从命令读取文件列表,并要求用户输入每个文件。我使用一个read
来读取文件名,另一个来获取用户输入,但是这个脚本似乎进入了无限循环。
foo () {
echo "a\nb\nc" | while read conflicted_file;
do
echo $conflicted_file
while true; do
read -e -p "> " yn
case $yn in
[nN]* ) echo "success"; break;;
[yY]* ) echo "fail"; break;;
* ) echo "invalid input";;
esac
done
done;
}
foo
去掉外层while read
似乎可以解决问题。有什么想法吗?
答案1
read
从标准输入读取,因此这两个s 都将通过在其标准输入上打开的同一管道read
从输出中读取。echo
为了让read
循环内部从管道外部的标准输入读取,您可以这样做:
foo () {
printf 'a\nb\nc\n' |
while IFS= read -r conflicted_file; do
printf '%s\n' "$conflicted_file"
while true; do
IFS= read <&3 -re -p "> " yn
case $yn in
[nN]* ) echo "success"; break;;
[yY]* ) echo "fail"; break;;
* ) echo "invalid input";;
esac
done
done
} 3<&0
也就是说,将其复制到foo
函数的整个函数体的 fd 3 上。
答案2
“读取”操作尝试从管道而不是 tty 读取。对此有几个解决方案。
- 跑步
read ... </dev/tty
。只要您的 foo() 函数不希望有重定向输入,这就可以工作。 将管道重定向到另一个文件描述符并循环读取该文件描述符,以便内部读取调用不受影响。
就像是:
exec 3< <(echo "a\nb\nc") while read -u 3 conflicted_file; do ... read -e -p "> " yn ... done exec 3>&-