case
我的目标是使用(仅使用+ )验证数字范围esac
,并打印该范围。例如:
- 如果数字在 0 到 80 之间,则打印
>=0<=80
- 如果数字在 81 到 100 之间,则打印
>=81<=100
- ETC。
下面我的脚本的问题是仅打印>=0<=90
0 到 9 之间的数字。如何修复我的脚本,以便它根据数字范围打印正确的输出?
#!/bin/ksh
read number
case $number in
[0-80]) echo ">=0<=80";;
[81-100]) echo ">=81<=100";;
[101-120]) echo ">=101<=120";;
[121-300]) echo ">=121<=300";;
esac
答案1
case
仅用于模式匹配,它不会进行算术评估(除非您考虑zsh
's<x-y>
扩展模式匹配运算符)。只是[...]
为了匹配一字符(或整理元素在一些实现中)基于其中指定的集合。例如[0-80]
会匹配一字符,如果它是0
to8
或之一0
(即 0、1、2、3、4、5、6、7、8 之一)。
您可以将数字与以下模式相匹配:
case $(($number)) in
([0-9]|[1-7][0-9]|80) echo ">=0<=80";;
(8[1-9]|9[0-9]|100) echo ">=81<=100";;
... and so on
esac
但您可以很容易地看出它不是正确的工具。
比赛[...]
一字符针对指定字符列表,因此[121-300]
匹配 1、2、1 到 3、0 或 0 的任何字符,因此它与[0-3]
or相同[0123]
。
使用:
if [ "$number" -ge 0 ] && [ "$number" -le 80 ]; then
echo ">=0<=80"
elif [ "$number" -ge 81 ] && [ "$number" -le 100 ]; then
echo ">=81<=100"
elif ... and so on
...
fi
另一种使用方法case
如下:
case $((
(number >= 0 && number <= 80) * 1 +
(number > 80 && number <= 100) * 2 +
(number > 100 && number <= 120) * 3 +
(number > 120 && number <= 300) * 4)) in
(1) echo ">=0<=80";;
(2) echo ">=81<=100";;
(3) echo ">=101<=120";;
(4) echo ">=121<=300";;
(0) echo "None of the above";;
esac
或者使用三元运算符 ( x ? y : z
):
case $((
number >= 0 && number <= 80 ? 1 :
number > 80 && number <= 100 ? 2 :
number > 100 && number <= 120 ? 3 :
number > 120 && number <= 300 ? 4 : 0)) in...
或者像 @mikeserv 一样,跳出固有思维模式,反转case
逻辑并与1
这些算术比较的值进行匹配。
答案2
事实上这真的很容易做到。问题在于case
,它总是只会扩展找到与模式的第一个匹配项所需的大小。这是规范的行为。因此,您只需使用已知字符串进行设置并评估模式的扩展即可。
case 1:${number:--} in
(1:*[!0-9]*|1:0*[89]*)
! echo NAN
;;
($((number<81))*)
echo "$number >=0<=80"
;;
($((number<101))*)
echo "$number >=81<=100"
;;
($((number<121))*)
echo "$number >=101<=120"
;;
($((number<301))*)
echo "$number >=121<=300"
;;
esac
case
为了在模式中找到前导 1,永远不会扩展这些模式。这在处理用户输入时尤其重要,因为这意味着您可以在$number
尝试将其放入算术扩展上下文中之前安全地验证其内容,该上下文与您实际将其放入数学扩展中的情况相同。
答案3
这不是很好,但你可以使用这个:
#!/bin/ksh
read number
case $number in
[0-9]|[1-7][0-9]|80) echo echo ">=0<=80";;
8[1-9]|9[0-9]|100) echo ">=81<=100";;
10[1-9]|11[0-9]|120) echo ">=101<=120";;
12[1-9]|130) echo ">=121<=300";;
esac