第一章: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

 

 

 

 

 

 

 

 

 

 

posted @ 2012-12-06 10:49  十舍七匹狼  阅读(1014)  评论(0)    收藏  举报