我写了这个案例选择陈述拒绝工作,我无法弄清楚我做错了什么。任何帮助表示赞赏。感谢。
echo; echo "Did you see a display?"
select YN in "yes" "no" ; do
case $YN in
yes)
echo "$2 at $X x $Y @$REF Hz">>/root/ran.log
break
;;
no)
echo "$2 at $X x $Y @$REF Hz">>/root/didntrun.log
break
;;
esac
done
这是代码的这部分的bash -x输出。 #?在屏幕上重复多次并跳过提示用户并跳转到代码的下一部分。
+ echo 'Did you see a display?'
Did you see a display?
+ select yn in '"yes"' '"no"'
1) yes
2) no
#? + case $yn in
#? + case $yn in
#? + case $yn in
#? + case $yn in
#? + case $yn in
#? + case $yn in
#? + case $yn in
#? + case $yn in
#? + case $yn in
#? + case $yn in
#? + case $yn in
#? + case $yn in
#? + case $yn in
#? + case $yn in
#? + case $yn in
#? + case $yn in
#?
编辑:想象一下,因为在从文件中读取行的循环之间调用了选择代码。将stdin更改为文件会导致select跳过用户提示并尝试从文件读取。现在我需要一种解决方法。
编辑2: 这是调用fnUseResolution函数的代码,其中包含select语句。
res.log在格式中的每一行都有分辨率,例如1920 1080 60
FILE=res.log
BAKIFS=$IFS
IFS=$(echo -en "\n\b")
exec 3<&0
exec 0<$FILE
while read -r LINE
do
fnUseResolution $LINE app1
fnUseResolution $LINE app2
fnUseResolution $LINE app3
done
exec 0<&3
IFS=$BAKIFS
答案 0 :(得分:2)
这对我来说很好,它会停止并允许我输入1
或2
。
请参阅以下成绩单:
pax$ cat qq.sh
echo "Did you see a display?"
select YN in "yes" "no" ; do
case $YN in
yes)
echo YES
break
;;
no)
echo NO
break
;;
esac
done
pax$ ./qq.sh
Did you see a display?
1) yes
2) no
#? 1
YES
pax$ ./qq.sh
Did you see a display?
1) yes
2) no
#? 2
NO
pax$ _
您确定此时标准输入已连接到您的终端吗?
由于您已经确认我怀疑您的标准输入未连接到终端,因此 通过摆弄文件句柄来修复它是一种有点棘手的方法。
考虑以下代码,它执行您在注释中指定的内容(调用函数接受来自已重定向标准输入的循环内的标准输入):
fn() {
echo "Did you see a display?"
select YN in "yes" "no" ; do
case $YN in
yes)
echo YES $YN $REPLY
break
;;
no)
echo NO $YN $REPLY
break
;;
esac
done
}
echo 'A
B
C
D' | while read ; do
echo $REPLY
fn
echo ====
done
如果您运行此代码,您将看到:
A
Did you see a display?
1) yes
2) no
#? #? #? #?
=====
这表明输入是在两个读者while read
和select
之间混合的。
解决这个问题的诀窍是通过更改代码来解除两个读者的关联:
(echo 'A
B
C
D' | while read ; do
echo $REPLY
fn <&4
done) 4<&0
这个输出是:
A
Did you see a display?
1) yes
2) no
#? 1 <- my input.
YES yes 1
=====
B
Did you see a display?
1) yes
2) no
#? 2 <- my input.
NO no 2
=====
C
Did you see a display?
1) yes
2) no
#? 1 <- my input.
YES yes 1
=====
D
Did you see a display?
1) yes
2) no
#? 2 <- my input.
NO no 2
=====
这样做(以它自己的可怕方式)是启动一个子shell来运行你的整个事情,诀窍是子shell首先连接当前标准输入(可能是终端)到文件处理4供以后使用。
在子shell中,运行正常的while read
循环,将标准输入(文件处理程序0)更改为从echo
语句中读取。
但是这里的诀窍是:当你调用你的函数时,你告诉它从文件句柄4而不是当前文件句柄0获取它的标准输入。因为它连接到保存的原始标准输入,它赢了“从while read
标准输入(echo
的输出)得到任何东西。
这可能需要一些时间来包裹你的脑袋(我记得第一次看到这个时我不得不从地板上摘下脑袋,因为我的头部爆炸了)。但是,一旦你了解它是如何工作的,你就会看到它的优雅: - )
这个输出是:
A
Did you see a display?
1) yes
2) no
#? 1
YES yes 1
=====
B
Did you see a display?
1) yes
2) no
#? 2
NO no 2
=====
C
Did you see a display?
1) yes
2) no
#? 1
YES yes 1
=====
D
Did you see a display?
1) yes
2) no
#? 2
NO no 2
=====
而且,基于你的代码,可能一个好的起点是围绕整个批次以保留标准输入,如:
(FILE=res.log
BAKIFS=$IFS
IFS=$(echo -en "\n\b")
exec 3<&0
exec 0<$FILE
while read -r LINE
do
fnUseResolution $LINE app1 <&4
fnUseResolution $LINE app2 <&4
fnUseResolution $LINE app3 <&4
done
exec 0<&3
IFS=$BAKIFS) 4<&0
我假设你的功能是fnUseResolution
。
但是,在查看该代码时,为read
而不是select
使用不同的文件句柄可能更简单,因为您可以比我想象的更能控制它。
试试:
FILE=res.log
BAKIFS=$IFS
IFS=$(echo -en "\n\b")
#exec 3<&0
exec 4<$FILE
while read -u 4 -r LINE
do
fnUseResolution $LINE app1
fnUseResolution $LINE app2
fnUseResolution $LINE app3
done
#exec 0<&3
IFS=$BAKIFS
-u 4
选项读取它以使用文件句柄4而不是0,我更改了exec
以匹配它。我没有测试过,但它应该正常工作。
通过这样做,你永远不会改变标准输入,所以在功能中它应该没问题。此外,在这种情况下,没有理由在文件句柄3中保存/恢复它,因此我已经对这些exec
调用进行了评论。
答案 1 :(得分:0)
这应该有用; Bash将用户响应返回给变量$ REPLY。 如果您输入“是”或“否”,这将起作用。
echo; echo "Did you see a display?"
select YN in "yes" "no" ; do
case $REPLY in
yes)
echo "$2 at $X x $Y @$REF Hz">>/root/ran.log
break
;;
no)
echo "$2 at $X x $Y @$REF Hz">>/root/didntrun.log
break
;;
*)
echo "blah! blah! $REPLY"
break
esac
done