嵌套读取语句导致 bash 中的无限循环

嵌套读取语句导致 bash 中的无限循环

我正在尝试从命令读取文件列表,并要求用户输入每个文件。我使用一个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 读取。对此有几个解决方案。

  1. 跑步read ... </dev/tty。只要您的 foo() 函数不希望有重定向输入,这就可以工作。
  2. 将管道重定向到另一个文件描述符并循环读取该文件描述符,以便内部读取调用不受影响。

    就像是:

    exec 3< <(echo "a\nb\nc")
    
    while read -u 3 conflicted_file; do
       ...
       read -e -p  ">  " yn
       ...
    done
    
    exec 3>&-
    

相关内容