我正在编写一个 bash 脚本,想要添加一些简单的验证测试。输入应该是1
or2
并且脚本应该再次要求输入,直到给出正确的输入。
我正在考虑使用until
循环来做到这一点,但它不起作用。我绑定了until [ $group -eq 1 ]
($group
用户给出的值在哪里),但显然我还需要第二个输入。我怎样才能正确地做到这一点?
答案1
until
printf 'Please enter 1 or 2: '
IFS= read -r line || exit # exit on EOF
[ "$line" = 1 ] || [ "$line" = 2 ]
do
printf >&2 '"%s" is neither 1 nor 2, try again.\n' "$line"
done
使用IFS=
和-r
,输入行将按原样存储在 中$line
。您可能希望省略,以便自动从输入的开头或结尾删除IFS=
空格(假设您没有修改)。$IFS
如果输入只能是1
或2
字符串,那么您需要使用=
,而不是-eq
。
如果您想允许使用其他表达式1
或2
数字,例如01
, 1+1
, 1.0
, 100e-2
, exp(0)
, RANDOM
(有时),那么您可以使用-eq
,但请注意,并非所有 shell 都接受上述所有类型的表达式(ksh93
将接受所有类型,但bash
仅接受诸如1
(前导和/或尾随空白)之类的内容,或0001
(前导零)),这意味着您将收到未形成有效算术表达式的输入的错误消息。
对于解释算术表达式的 shell,这也很危险,因为它可以更改变量值(例如对于像 之类的输入PATH=123
),甚至运行任意命令(例如对于像 之类的输入a[0$(cmd>&2)]
)。
根据 shell 的不同,您还可能会在 18446744073709551617 或 4294967297(或 2 32或 2 64 + 1 或 2的任何其他倍数)上得到误报,因为大多数 shell 使用 64 位或 32 位整数。
无论你做什么,就做不是使用-o
and-a
二元test
/[
运算符。那些应该被驱逐它们使得命令的解析[
可能不明确并且在实践中不可靠(现在被标记为过时的在 POSIX 规范中)。
例如:
$ line='!' sh -c '[ "$line" = 1 -o "$line" = 2 ]'
sh: line 0: [: too many arguments
并记住引用您的变量("$line"
而不是$line
会进行 split+glob 的变量)。
答案2
这应该可行,将它们与或(-o
)结合起来:
#init group variable
group=0
#read until value is either 1 or 2
until [ $group -eq 1 -o $group -eq 2 ];
do
#your script...
#read user input and put it in group
read -p "Which group?" group
done
您还可以使用||
as 或 运算符:
until [ $group -eq 1 ] || [ $group -eq 2 ]
尽管在某些情况下,例如当您使用错误代码 ( $?
) 时,第一个选项更好,请参阅这个答案。
答案3
while IFS= read -r; do
case "$REPLY" in
1|2) break ;;
*) echo 'Error' >&2 ;;
esac
done
此代码片段从标准输入读取一个值,然后针对1
和进行测试2
。如果匹配任一字符串,则循环退出,否则会生成简洁的诊断消息并继续循环。
答案4
只需使用以下命令将第二个条件添加到表达式中或者操作员-o
。