bash while循环结构不正确
我有三种不同的用户输入需要确认,我在循环时通过“是否正确:是或否”来确认。显然,我的代码是错误的,因为尽管第一个循环执行正确,但我的脚本只测试这些循环,然后执行其他两个循环。请参阅下面的代码。如有任何见解,将不胜感激bash while循环结构不正确,bash,loops,while-loop,Bash,Loops,While Loop,我有三种不同的用户输入需要确认,我在循环时通过“是否正确:是或否”来确认。显然,我的代码是错误的,因为尽管第一个循环执行正确,但我的脚本只测试这些循环,然后执行其他两个循环。请参阅下面的代码。如有任何见解,将不胜感激 #loop 1 while [ "$answer" != "Yes" ] do stuff read answer done #loop 2 while [ "$answer" != "Yes" ] do stuff read answer done #loop 3 while
#loop 1
while [ "$answer" != "Yes" ]
do
stuff
read answer
done
#loop 2
while [ "$answer" != "Yes" ]
do
stuff
read answer
done
#loop 3
while [ "$answer" != "Yes" ]
do
stuff
read answer
done
当
$answer
包含Yes
时,第一个循环结束。然后第二个循环立即执行相同的测试,测试失败,因此循环立即结束。第三个循环也会发生同样的情况
您应该清除循环之间的$answer
:
#loop 1
while [ "$answer" != "Yes" ]
do
stuff
read answer
done
answer=
#loop 2
while [ "$answer" != "Yes" ]
do
stuff
read answer
done
answer=
#loop 3
while [ "$answer" != "Yes" ]
do
stuff
read answer
done
当
$answer
包含Yes
时,第一个循环结束。然后第二个循环立即执行相同的测试,测试失败,因此循环立即结束。第三个循环也会发生同样的情况
您应该清除循环之间的$answer
:
#loop 1
while [ "$answer" != "Yes" ]
do
stuff
read answer
done
answer=
#loop 2
while [ "$answer" != "Yes" ]
do
stuff
read answer
done
answer=
#loop 3
while [ "$answer" != "Yes" ]
do
stuff
read answer
done
根据我们在评论中的讨论,这里有一个
unset
和var=
的快速示例,以及一个函数tesyn
,该函数显示了在响应用户输入时测试的不同用途。函数在yes
上返回0
(bash true),在no
上返回1
(bash false),允许在提问后进行简单的测试构造
#!/bin/bash
function testyn {
local answer
read answer
while : ; do
answer=$(tr 'A-Z' 'a-z' <<<$answer) # translate answer to lower-case
case "$answer" in
yes )
return 0
;;
no )
return 1
;;
* )
printf " Invalid Input, Enter (yes/no): "
read answer
;;
esac
done
}
printf "Continue? (yes/no): "
while read answer && [ "$answer" != yes ]; do
printf " Invalid input, (yes/no): "
done
unset answer
printf "Continue? (yes/no): "
while read answer && [ "$answer" != yes ]; do
printf " Invalid input, (yes/no): "
done
answer=
printf "Continue? (yes/no): "
while read answer && [ "$answer" != yes ]; do
printf " Invalid input, (yes/no): "
done
## call function tesyn after a question, then
# use any test that tests for 1 or 0 to
# respond to the answer
printf "\n Would you like to continue? (y/n): "
testyn || {
printf "\nanswer was no, exiting...\n\n"
exit 1
}
printf "\nAnswer must have been 'yes'. All Done!\n\n"
exit 0
根据我们在评论中的讨论,这里有一个
unset
和var=
的快速示例,以及一个函数tesyn
,该函数显示了在响应用户输入时测试的不同用途。函数在yes
上返回0
(bash true),在no
上返回1
(bash false),允许在提问后进行简单的测试构造
#!/bin/bash
function testyn {
local answer
read answer
while : ; do
answer=$(tr 'A-Z' 'a-z' <<<$answer) # translate answer to lower-case
case "$answer" in
yes )
return 0
;;
no )
return 1
;;
* )
printf " Invalid Input, Enter (yes/no): "
read answer
;;
esac
done
}
printf "Continue? (yes/no): "
while read answer && [ "$answer" != yes ]; do
printf " Invalid input, (yes/no): "
done
unset answer
printf "Continue? (yes/no): "
while read answer && [ "$answer" != yes ]; do
printf " Invalid input, (yes/no): "
done
answer=
printf "Continue? (yes/no): "
while read answer && [ "$answer" != yes ]; do
printf " Invalid input, (yes/no): "
done
## call function tesyn after a question, then
# use any test that tests for 1 or 0 to
# respond to the answer
printf "\n Would you like to continue? (y/n): "
testyn || {
printf "\nanswer was no, exiting...\n\n"
exit 1
}
printf "\nAnswer must have been 'yes'. All Done!\n\n"
exit 0
您可能希望对函数使用更结构化的方法(更干燥)
您可能希望对函数使用更结构化的方法(更干燥)
您可以通过两种方式清除答案,一种是如上所述的
answer=
,另一种是使用unset answer
。两者都做同样的事情,这只是一个偏好问题。@David C.Rankin-使用unset关键字似乎更好。任何一种方法都可以。1/2手册用var=
解释,另1/2使用unset var
。避免此问题的一种方法是编写执行测试的testyn()
函数。这样一来,所有变量都是测试函数的局部变量,不能影响脚本的其余部分。@Barmar,David C.Rankin-mmm…不,在循环之间添加未设置的答案在我的脚本中不起作用,因为脚本只是测试这些循环。也许我应该澄清一下:我希望循环1一直运行到是。循环2运行,直到是。循环3运行,直到是。目前,只要循环1收到Yes,运行时就结束。请提供测试用例的工作版本。我也会写一篇。您的原始问题中未显示的其他问题。您可以通过两种方式清除答案,或者如上所述的answer=
,或者使用unset-answer
。两者都做同样的事情,这只是一个偏好问题。@David C.Rankin-使用unset关键字似乎更好。任何一种方法都可以。1/2手册用var=
解释,另1/2使用unset var
。避免此问题的一种方法是编写执行测试的testyn()
函数。这样一来,所有变量都是测试函数的局部变量,不能影响脚本的其余部分。@Barmar,David C.Rankin-mmm…不,在循环之间添加未设置的答案在我的脚本中不起作用,因为脚本只是测试这些循环。也许我应该澄清一下:我希望循环1一直运行到是。循环2运行,直到是。循环3运行,直到是。目前,只要循环1收到Yes,运行时就结束。请提供测试用例的工作版本。我也会写一篇。您的原始问题中未显示的其他问题正在发生。如果read
本身失败,您的测试将全部失败:当提示输入yes/no时,尝试输入EOF(Ctrl-D)并享受您美丽的错误。目的不是陷阱EOF。您可以整天按ctrl+d键,对测试所做的只是重新打印提示行。输入(是/否),它将正常工作,输入任何其他内容,系统将再次提示您。我相信你的讽刺与你的年龄和成熟度成正比。它不需要也不受欢迎。让我们与您的答案进行比较。目的是确保用户确实希望继续。如中所示,是否确实要删除该文件?现在自己试试:printf“继续?(是/否):”;阅读答案时&&[“$answer”!=yes];不打印“无效输入,(是/否):”;完成;回显“您键入的是”
。在提示时键入EOF,您将看到您键入的yes
将被回显,程序将愉快地继续。嗯,作为一个用户,我不希望程序会这样。现在,如果这是您想要的行为,您应该清楚地提到它,正如在我的书中,这是一个危险的行为。如果读取本身失败,您的测试都会失败:当提示输入是/否时,尝试输入EOF(Ctrl-D)并享受您美丽的错误。目的不是陷阱EOF。您可以整天按ctrl+d键,对测试所做的只是重新打印提示行。输入(是/否),它将正常工作,输入任何其他内容,系统将再次提示您。我相信你的讽刺与你的年龄和成熟度成正比。它不需要也不受欢迎。让我们与您的答案进行比较。目的是确保用户确实希望继续。如中所示,是否确实要删除该文件?现在自己试试:printf“继续?(是/否):”;阅读答案时&&[“$answer”!=yes];不打印“无效输入,(是/否):”;完成;回显“您键入的是”
。在提示时键入EOF,您将看到您键入的“是”将被回显,并且pro