嵌套 bash while 循环不接受用户输入
nested bash while loop not taking user input
我正在尝试在 bash 中编写(Mac OSX 但安装了 GNU shell 程序)一个 "Yes or No" 交互式逐行迭代从输入文件中读取。例如,假设我有一个文件,其中包含 1 到 5(一行一个)的数字作为输入,我想询问它们是否是素数。
#!bin/bash
while read NUMBER
do echo "Prime number (answer y or n)?"
while read ANSWER
do
test "$ANSWER" == "y" && echo "Prime" && break
test "$ANSWER" == "n" && echo "Non-prime" && break
test "$ANSWER" != "y" -a "$ANSWER" != "n" && echo "Type y or n"
done
done < 1_to_5_file.txt
以下输出不会打开以供用户输入
Prime number (answer y or n)?
Type y or n
Type y or n
Type y or n
因为外部 while 循环的标准输入(脚本的输入)设置为从 1_to_5_file.txt 读取,它会继承到 while 循环内的所有命令 运行。解决这个问题的一种方法是将原始标准输入保存在不同的描述符中,然后我们可以在循环中使用它。在我的示例中,我会将其存储在文件描述符 3.
中
#!/bin/bash
while read NUMBER
do echo "Prime number (answer y or n)?"
while read ANSWER
do
test "$ANSWER" == "y" && echo "Prime" && break
test "$ANSWER" == "n" && echo "Non-prime" && break
test "$ANSWER" != "y" -a "$ANSWER" != "n" && echo "Type y or n"
done 0<&3
done 3<&0 < 1_to_5_file.txt
最后一行在文件描述符3中复制文件描述符0。然后在循环中文件描述符3指向原始标准输入。在内部 while 循环的最后一行,然后我将文件描述符 3 复制到文件描述符 0,从而使循环内的标准输入再次指向原始标准输入。
郑重声明,“<”等同于“0<”,“>”等同于“1>”。因此 0<&3
也可以写成 <&3
.
@chepner 提出的另一个更优雅的解决方案是打开文件描述符 3 上的 1_to_5_file.txt,而只是将第一个读取命令更改为从该命令读取:
#!/bin/bash
while read NUMBER <&3
do echo "Prime number (answer y or n)?"
while read ANSWER
do
test "$ANSWER" == "y" && echo "Prime" && break
test "$ANSWER" == "n" && echo "Non-prime" && break
test "$ANSWER" != "y" -a "$ANSWER" != "n" && echo "Type y or n"
done
done 3< 1_to_5_file.txt
请注意,与问题中的代码相比,最后一行有 3<
而不是 3
.
我正在尝试在 bash 中编写(Mac OSX 但安装了 GNU shell 程序)一个 "Yes or No" 交互式逐行迭代从输入文件中读取。例如,假设我有一个文件,其中包含 1 到 5(一行一个)的数字作为输入,我想询问它们是否是素数。
#!bin/bash
while read NUMBER
do echo "Prime number (answer y or n)?"
while read ANSWER
do
test "$ANSWER" == "y" && echo "Prime" && break
test "$ANSWER" == "n" && echo "Non-prime" && break
test "$ANSWER" != "y" -a "$ANSWER" != "n" && echo "Type y or n"
done
done < 1_to_5_file.txt
以下输出不会打开以供用户输入
Prime number (answer y or n)?
Type y or n
Type y or n
Type y or n
因为外部 while 循环的标准输入(脚本的输入)设置为从 1_to_5_file.txt 读取,它会继承到 while 循环内的所有命令 运行。解决这个问题的一种方法是将原始标准输入保存在不同的描述符中,然后我们可以在循环中使用它。在我的示例中,我会将其存储在文件描述符 3.
中#!/bin/bash
while read NUMBER
do echo "Prime number (answer y or n)?"
while read ANSWER
do
test "$ANSWER" == "y" && echo "Prime" && break
test "$ANSWER" == "n" && echo "Non-prime" && break
test "$ANSWER" != "y" -a "$ANSWER" != "n" && echo "Type y or n"
done 0<&3
done 3<&0 < 1_to_5_file.txt
最后一行在文件描述符3中复制文件描述符0。然后在循环中文件描述符3指向原始标准输入。在内部 while 循环的最后一行,然后我将文件描述符 3 复制到文件描述符 0,从而使循环内的标准输入再次指向原始标准输入。
郑重声明,“<”等同于“0<”,“>”等同于“1>”。因此 0<&3
也可以写成 <&3
.
@chepner 提出的另一个更优雅的解决方案是打开文件描述符 3 上的 1_to_5_file.txt,而只是将第一个读取命令更改为从该命令读取:
#!/bin/bash
while read NUMBER <&3
do echo "Prime number (answer y or n)?"
while read ANSWER
do
test "$ANSWER" == "y" && echo "Prime" && break
test "$ANSWER" == "n" && echo "Non-prime" && break
test "$ANSWER" != "y" -a "$ANSWER" != "n" && echo "Type y or n"
done
done 3< 1_to_5_file.txt
请注意,与问题中的代码相比,最后一行有 3<
而不是 3
.