第一章:The Missing Code Library--6.合法化浮点数输入
咋一看,在一个shell脚本中合法化一个浮点值的过程看起来有些挫,但想想看浮点数也不过就是一个用小数点分割开来的2个整数。联系第5个脚本validint.sh,你会发现浮点数合法化的测试短的让人惊讶。
代码:
validfloat.sh
1 #!/bin/sh
2
3 # validfloat.sh -- 测试一个值是否是合法的浮点数
4 # 注意,这个脚本并不能接受科学记数法形式的数字
5
6 # 为了测试是否合法,我们需要在小数点位置分割数字。
7 # 然后测试第一个部分,看看是不是一个合法的整数
8 # 然后测试第二个,看看是不是>=0的整数。
9 # 所以-30.5合法,-30.-8非法。
10
11 source validint.sh
12
13 validfloat()
14 {
15 fvalue="$1"
16
17 if [ ! -z $(echo $fvalue | sed 's/[^.]//g') ]; then
18
19 decimalPart="$(echo $fvalue | cut -d. -f1)"
20 fractionalPart="$(echo $fvalue | cut -d. -f2)"
21
22 if [ ! -z $decimalPart ]; then
23 if ! validint "$decimalPart" "" ""; then
24 return 1
25 fi
26 fi
27
28 if [ "${fractionalPart%${fractionalPart#?}}" = "-" ]; then
29 echo "Invalid floating-point number: '-' not allowed \
30 after decimal point" >&2
31 return 1
32 fi
33
34 if [ "$fractionalPart" != "" ]; then
35 if ! validint "$fractionalPart" "0" ""; then
36 return 1
37 fi
38 fi
39
40 if [ "$decimalPart" = "-" -o -z "$decimalPart" ]; then
41 if [ -z $fractionalPart ]; then
42 echo "Invalid floating-point format." >&2
43 fi
44 fi
45
46 else
47 if [ "$fvalue" = "-" ]; then
48 echo "Invalid floating-point format." >&2
49 return 1
50 fi
51
52 if ! validint "$fvalue" "" ""; then
53 return 1
54 fi
55
56 fi
57
58 return 0
59 }
60
61 if validfloat $1; then
62 echo "$1 is a valid floating-point value"
63 fi
运行脚本:
调用函数的时候,如果没有报错信息,返回码是0,给定的数字就是一个合法的浮点数。通过增加下面几行到脚本中来测试下:
1 if validfloat $1; then 2 echo "$1 is a valid floating-point value" 3 fi
运行结果:
1 ./validfloat.sh 1234.56 2 1234.56 is a valid floating-point value 3 ./validfloat.sh -1234.56 4 -1234.56 is a valid floating-point value 5 ./validfloat.sh -.75 6 -.75 is a valid floating-point value 7 ./validfloat.sh -11.-12 8 Invalid floating-point number: '-' not allowed after decimal point 9 ./validfloat.sh 1.0344e22 10 错误的数字格式!只有数字,不能有逗号、空格等
在此提示下,在上面的脚本中用source引入validint.sh的时候,记得把validint中的最后几行测试脚本注释掉,否则会报错的。source的用法可具体参考手册页。
分析脚本:
对上面的脚本的最好的扩展就是让它支持科学记数法。就是最后一个测试的内容。这个并不是
太难。你要测试下有没有'e'或'E',然后将结果分割为3个部分:
小数点前的部分,只有一个数字;
小数部分;
指数部分。
最后确保每个部分都是整数。
老七我自己想了一会,写了一个,欢迎大家指正:
测试科学记数法
1 validfloat()
2 {
3 fvalue="$1"
4 delimiter="$(echo $fvalue | sed 's/[^e|^E]//g')"
5
6 if [ ! -z $delimiter ]; then #测试下是否有e或E
7
8 if [ ${#delimiter} -ne 1 ]; then #e或E不能有多个
9 echo "only one e or E."
10 return 1
11 fi
12
13 decimalPart="$(echo $fvalue | cut -d. -f1)" #小数点前部分
14 part="$(echo $fvalue | cut -d. -f2-)" #小数点后部分,注意f2后有一小横,目的是输出剩下的所有域
15 fractionalPart="$(echo $part | cut "-d$delimiter" -f1)" #小数点后,e前部分
16 exponent="$(echo $part | cut "-d$delimiter" -f2)" #e后部分
17
18 if ! validint "$decimalPart" "-9" "9"; then #测试小数点前的部分是不是一个数字,即0-9范围内
19 echo "scientific notation's decimal part abs must in [0-9]."
20 return 1
21 fi
22
23 if [ "${fractionalPart%${fractionalPart#?}}" = '-' ]; then #测试小数部分第一个符号是不是负号
24 echo "scientific notation's fractional portion cannot be negative."
25 return 1
26 fi
27
28 if [ "$fractionalPart" = "" ]; then #测试小数部分是不是为空
29 echo "scientific notation's fractional portion is empty."
30 return 1
31 else
32 if ! validint "$fractionalPart" "" ""; then #测试小数部分是不是整数
33 echo "scientific notation's fractional portion is not integer."
34 return 1
35 fi
36 fi
37
38 if ! validint "$exponent" "" ""; then
39 echo "scientific notation's exponent not integer."
40 return 1
41 fi
42
43 elif [ ! -z $(echo $fvalue | sed 's/[^.]//g') ]; then
下面的代码和上面的都一样了。然后测试下:
1 ./validfloat2.sh 1.0EEe22 2 only one e or E. 3 ./validfloat2.sh 1.-3E22 4 scientific notation's fractional portion cannot be negative. 5 /validfloat2.sh 1.34E-22.35 6 错误的数字格式!只有数字,不能有逗号、空格等 7 scientific notation's exponent not integer. 8 ./validfloat2.sh 1.013E22 9 1.013E22 is a valid floating-point value
最后,整理下书上的,和自己写的:
validfloatNew.sh
1 #!/bin/sh 2 3 source validint.sh 4 5 validfloat() 6 { 7 fvalue="$1" 8 delimiter="$(echo $fvalue | sed 's/[^e|^E]//g')" 9 10 if [ ! -z $delimiter ]; then #测试下是否有e或E 11 12 if [ ${#delimiter} -ne 1 ]; then #e或E不能有多个 13 echo "only one e or E." 14 return 1 15 fi 16 17 decimalPart="$(echo $fvalue | cut -d. -f1)" #小数点前部分 18 part="$(echo $fvalue | cut -d. -f2-)" #小数点后部分,注意f2后有一小横,目的是输出剩下的所有域 19 fractionalPart="$(echo $part | cut "-d$delimiter" -f1)" #小数点后,e前部分 20 exponent="$(echo $part | cut "-d$delimiter" -f2)" #e后部分 21 22 if ! validint "$decimalPart" "-9" "9"; then #测试小数点前的部分是不是一个数字,即0-9范围内 23 echo "scientific notation's decimal part abs must in [0-9]." 24 return 1 25 fi 26 27 if [ "${fractionalPart%${fractionalPart#?}}" = '-' ]; then #测试小数部分第一个符号是不是负号 28 echo "scientific notation's fractional portion cannot be negative." 29 return 1 30 fi 31 32 if [ "$fractionalPart" = "" ]; then #测试小数部分是不是为空 33 echo "scientific notation's fractional portion is empty." 34 return 1 35 else 36 if ! validint "$fractionalPart" "" ""; then #测试小数部分是不是整数 37 echo "scientific notation's fractional portion is not integer." 38 return 1 39 fi 40 fi 41 42 if ! validint "$exponent" "" ""; then 43 echo "scientific notation's exponent not integer." 44 return 1 45 fi 46 47 elif [ ! -z $(echo $fvalue | sed 's/[^.]//g') ]; then 48 49 decimalPart="$(echo $fvalue | cut -d. -f1)" 50 fractionalPart="$(echo $fvalue | cut -d. -f2)" 51 52 if [ ! -z $decimalPart ]; then 53 if ! validint "$decimalPart" "" ""; then 54 return 1 55 fi 56 fi 57 58 if [ "${fractionalPart%${fractionalPart#?}}" = "-" ]; then 59 echo "Invalid floating-point number: '-' not allowed \ 60 after decimal point" >&2 61 return 1 62 fi 63 64 if [ "$fractionalPart" != "" ]; then 65 if ! validint "$fractionalPart" "0" ""; then 66 return 1 67 fi 68 fi 69 70 if [ "$decimalPart" = "-" -o -z "$decimalPart" ]; then 71 if [ -z $fractionalPart ]; then 72 echo "Invalid floating-point format." >&2 73 fi 74 fi 75 76 else 77 if [ "$fvalue" = "-" ]; then 78 echo "Invalid floating-point format." >&2 79 return 1 80 fi 81 82 if ! validint "$fvalue" "" ""; then 83 return 1 84 fi 85 86 fi 87 88 return 0 89 } 90 91 if validfloat $1; then 92 echo "$1 is a valid floating-point value" 93 fi

validfloat.sh
浙公网安备 33010602011771号