case + 如何在 case 语法中实现等于或小于或大于

case + 如何在 case 语法中实现等于或小于或大于

case我的目标是使用(仅使用+ )验证数字范围esac,并打印该范围。例如:

  • 如果数字在 0 到 80 之间,则打印>=0<=80
  • 如果数字在 81 到 100 之间,则打印>=81<=100
  • ETC。

下面我的脚本的问题是仅打印>=0<=900 到 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]会匹配字符,如果它是0to8或之一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

相关内容