yae*_*ael 9 shell ksh shell-script arithmetic
我的目标是使用(仅使用case+ esac)验证数字范围,并打印该范围。例如:
>=0<=80>=81<=100我下面的脚本的问题>=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
Run Code Online (Sandbox Code Playgroud)
case仅用于模式匹配,它不会进行算术评估(除非您考虑zsh的<x-y>扩展模式匹配运算符)。的[...]是仅匹配一个(或字符排序元素基于内指定的集合在一些实施方式)。因此,例如,[0-80]如果一个字符是0to 8or 之一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
Run Code Online (Sandbox Code Playgroud)
但是您可以很容易地看出它不是正确的工具。
The[...]匹配指定字符列表的一个字符,因此[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
Run Code Online (Sandbox Code Playgroud)
另一种使用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
Run Code Online (Sandbox Code Playgroud)
或者使用三元运算符 ( 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...
Run Code Online (Sandbox Code Playgroud)
或者像@mikeserv 一样,跳出框框思考,颠倒case逻辑并匹配1那些算术比较的值。
事实上这真的很容易做到。问题在于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
Run Code Online (Sandbox Code Playgroud)
case为了在模式中找到前导 1,永远不会扩展这些模式。$number这在处理用户输入时尤其重要,因为这意味着您可以在尝试将其放入算术扩展上下文中之前安全地验证其内容,该上下文与您实际将其放入数学扩展中的情况相同。