#!/bin/bash/
echo "Choose a number between 1 and 100"
read num
num=num
echo
if [ $num -lt 100 -o -gt 1 ]; then
echo "You chose $num"
elif [ $num -gt 100 -o -lt 1 ]; then
echo "you chose a number outside of the boundary"
fi
答案1
使用 POSIX sh 语法:
#! /bin/sh -
printf 'Choose a decimal integer number between 1 and 100: '
IFS= read -r num
die() {
printf >&2 '%s\n' "$@"
exit 1
}
case $num in
("" | - | *[!0123456789-]* | ?*-*)
die "$num is not a valid decimal integer number";;
(*[123456789]??*)
die "You chose a number outside the boundaries"
esac
if [ "$num" -lt 1 ] || [ "$num" -gt 100 ]; then
die "You chose a number outside the boundaries"
fi
echo "You chose $num"
- 数字是模棱两可的。
0xAA
,MMXVIII
,¾
,010
,1.4e+4
,infinity
都是根据某种定义的数字数字。许多类似 POSIX 的 shell,包括bash
在其内置中仅支持十进制整数[
(以及在其算术表达式中支持十进制、八进制、十六进制)。最好准确地限定您想要的数字类型。这里以十进制整数为例。 - 在算术表达式和
[
命令中的某些 shell 中使用任意字符串是命令注入漏洞。因此,您需要首先检查输入的数字是否看起来像一个数字。 IFS= read -r line
是读取一行输入的语法(尽管这里的$IFS
-stripping 和行继续处理read num
可能没问题)。- 参数扩展需要在类似 Bourne 的 shell 中引用
- 你的逻辑有问题。你用过或者代替和运算符。所有十进制数都大于 1或者少于 100。
-o
和运算符-a
[
已被弃用,因为它们会导致无法可靠解释的测试表达式。在这里,一旦我们确保参数是十进制整数,就不会出现问题,最好避免使用它们。最好使用[
由&&
或||
shell 运算符分隔的多个调用。- 最好在 stderr (
>&2
) 上输出错误消息,并在失败时以非零退出状态退出。 - 大多数 shell 使用编译器的本机整数数据类型作为整数运算符。对于大多数系统上的大多数 shell,例如 2 64 +50 (18446744073709551666) 对于该内部表示来说太大了。根据 shell 的
[
实现,它要么不被识别为数字(bash、dash、yash),要么被截断为 19 位并带有警告(zsh),要么被近似为浮点数(ksh93),要么被包装(因此被视为与 50) (mksh) 相同。所以你可能会发现[ 18446744073709551666 -gt 0 ]
返回 false,或者[ 18446744073709551666 -le 100 ]
返回 true。因此要*[123456789]??*
检查是否超过 3 位数字。 - 请注意,如果用户输入 NUL 字符作为其输入的一部分,则不同 shell 的行为会有所不同。
具体来说bash
,你可以通过以下方式让它稍微不那么尴尬:
#! /bin/bash -
IFS= read -rp 'Choose a decimal integer number between 1 and 100: ' num
die() {
printf >&2 '%s\n' "$@"
exit 1
}
[[ $num =~ ^-?[0123456789]+$ ]] ||
die "$num is not a valid decimal integer number"
[[ $num = *[123456789]??* ]] ||
((num < 1 || num > 100)) &&
die "You chose a number outside the boundaries"
echo "You chose $num"
答案2
使用外壳测试:
#!/bin/bash
read -rp "Choose a number between 1 and 100: " num
echo
if [ "$num" -le 100 -a "$num" -ge 1 ]; then
echo "You chose $num"
else
echo "you chose a number outside of the boundary"
fi
使用 bash 扩展测试:
#!/bin/bash
read -rp "Choose a number between 1 and 100: " num
echo
if [[ "$num" -le 100 && "$num" -ge 1 ]]; then
echo "You chose $num"
else
echo "you chose a number outside of the boundary"
fi
使用 shell 算术:
#!/bin/bash
read -rp "Choose a number between 1 and 100: " num
echo
if ((num<=100 && num>=1)); then
echo "You chose $num"
else
echo "you chose a number outside of the boundary"
fi
注意:您正在-o
使用或者但你似乎-a
想要和。 with 或 只需要通过一个条件,因此数字可以是 -1 或 101。
此外,右侧-o
就像一个全新的测试,因此您需要重新引入该侧的变量。此外,我只是使用else
而不是elif
语句,因为如果该数字未通过第一个测试,则无需对其执行另一次测试。
答案3
下面的第二行是一个致命的拼写错误(可能是num="$num"
),但如果它是正确的,则该行将是不必要的。
read num
num=num
如果用户输入数字“1”,第二行将其更改为非数字字符串“数字”。这将打破此后所有的数字限制检查。
要解决这个问题,只需删除第二行即可。