需求分析
我们在脚本中验证整数输入可谓是小菜一碟,但如果你也想接受负数的话,可就没那么容易了。问题在于每个数值只能有一个负号,而且还必须出现在数值的最开始部分。下面脚本可以确保正确地格式化负数,另外还能检查其值是否位于用户指定的区间内。
代码实现
#!/bin/sh
#filename:validint
#description:验证整数输入,允许出现负数。validint() {# 验证第一个参数并根据 最小值$2 和/或 最大值$3(如果指定的话)进行测试。# 如果第一个参数的值不在指定区间内或者不全是数字组成,那么脚本执行失败number="$1"; min="$2"; max="$3"# 判断输入是否为空if [ -z $number ]; thenecho "You didn't enter anything. Please enter a number." >&2return 1fi# 获取整数部分if [ "${number%${number#?}}" = "-" ]; then# 获取第一个字符以外的所有字符进行测试testvalue="${number#?}"elsetestvalue="$number"fi# 删除变量number中的所有数字,以作测试之用nodigits="$(echo $testvalue | sed 's/[[:digit:]]//g')"# 检查非数字字符if [ ! -z $nodigits ];thenecho "Invalid number format! Only digits, no commas, spaces, etc." >&2return 1fiif [ ! -z $min ];then# 输入值是否小于指定的最小值?if [ "$number" -lt "$min" ];thenecho "Your value is too small: smallest accpetable value is $min." >&2return 1fifiif [ ! -z $max ];then# 输入值是否大于指定的最大值if [ "$number" -gt "$max" ];thenecho "Your value is too big: largest acceptable value is $max." >&2return 1fifireturn 0
}#------------执行脚本----
# 验证输入
if validint "$1" "$2" "$3" ; thenecho "Input is a valid integer within your constraints."
fi
工作原理
验证整数非常简单,因为值要么是一连串数字(0至9,要么开头部分会有一个仅出现一次的负号。如果在调用validint()函数的时候指定了最小值或最大值(或同时给出了两者),那么它会对其做出检查,以确保输入的值位于区间内。
函数要确保不会出现用户不输入任何参数的情况(也要考虑到这个位置上可能会出现带有引号的空字符串,这一点很重要,以避免产生错误信息)。
然后查找负号,创建不包含任何数字的输入值。如果去除数字后的值长度不为0,说明输入有问题,测试失败
如果输入值有效,将其与指定的最小值和最大值做比较x。最后,如果函数出现错误,返回1;否则,返回0。
精益求精
注意,测试检查用户输入值的第一个字符是否为负号:if [ "${number%${number#?}}" = "-" ] ; then
如果第一个字符是负号,就将整数值的数字部分赋给变量testvalue。然后将其中所有的数字全部剔除,做进一步测试,原代码如下:
if [ ! -z $min ];then# 输入值是否小于指定的最小值?if [ "$number" -lt "$min" ];thenecho "Your value is too small: smallest accpetable value is $min." >&2return 1fi
fi
你可能会想用逻辑AND(-a)连接两个表达式,这样就可以少用一个嵌套if语句了。例如,下面的代码看起来应该没问题:
if [ ! -z $min -a "$number" -lt "$min" ] ; thenecho "Your value is too small: smallest acceptable value is $min." >&2 exit 1
fi
可惜事与愿违,因为即便AND的第一个条件被证明为假,你也无法保证第二个条件不会被测试(这一点和其他大多数编程语言不同)。这意味着,如果你打算采用这种写法,那么在比较的时候,可能会碰上由于无效或非预期值所造成的各种bug。事情本不该如此,但是是你自己要这么写的。