在shell脚本中合法化浮点数输入
咋一看,在一个shell脚本中合法化一个浮点值的过程看起来有些挫,但想想看浮点数也不过就是一个用小数点分割开来的2个整数。联系第5个脚本validint.sh,你会发现浮点数合法化的测试短的让人惊讶。
代码:
01
#!/bin/sh
02
03
# validfloat.sh -- 测试一个值是否是合法的浮点数
04
# 注意,这个脚本并不能接受科学记数法形式的数字
05
06
# 为了测试是否合法,我们需要在小数点位置分割数字。
07
# 然后测试第一个部分,看看是不是一个合法的整数
08
# 然后测试第二个,看看是不是>=0的整数。
09
# 所以-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
运行结果:
01
./validfloat.sh 1234.56
02
1234.56 is a valid floating-point value
03
./validfloat.sh -1234.56
04
-1234.56 is a valid floating-point value
05
./validfloat.sh -.75
06
-.75 is a valid floating-point value
07
./validfloat.sh -11.-12
08
Invalid floating-point number: '-' not allowed after decimal point
09
./validfloat.sh 1.0344e22
10
错误的数字格式!只有数字,不能有逗号、空格等
在此提示下,在上面的脚本中用source引入validint.sh的时候,记得把validint中的最后几行测试脚本注释掉,否则会报错的。source的用法可具体参考手册页。
分析脚本:
对上面的脚本的最好的扩展就是让它支持科学记数法。就是最后一个测试的内容。这个并不是
太难。你要测试下有没有'e'或'E',然后将结果分割为3个部分:
小数点前的部分,只有一个数字;
小数部分;
指数部分。
最后确保每个部分都是整数。
老七我自己想了一会,写了一个,欢迎大家指正:
01
#测试科学记数法
02
validfloat()
03
{
04
fvalue="$1"
05
delimiter="$(echo $fvalue | sed 's/[^e|^E]//g')"
06
07
if [ ! -z $delimiter ]; then #测试下是否有e或E
08
09
if [ ${#delimiter} -ne 1 ]; then #e或E不能有多个
10
echo "only one e or E."
11
return 1
12
fi
13
14
decimalPart="$(echo $fvalue | cut -d. -f1)" #小数点前部分
15
part="$(echo $fvalue | cut -d. -f2-)" #小数点后部分,注意f2后有一小横,目的是输出剩下的所有域
16
fractionalPart="$(echo $part | cut "-d$delimiter" -f1)" #小数点后,e前部分
17
exponent="$(echo $part | cut "-d$delimiter" -f2)" #e后部分
18
19
if ! validint "$decimalPart" "-9" "9"; then #测试小数点前的部分是不是一个数字,即0-9范围内
20
echo "scientific notation's decimal part abs must in [0-9]."
21
return 1
22
fi
23
24
if [ "${fractionalPart%${fractionalPart#?}}" = '-' ]; then #测试小数部分第一个符号是不是负号
25
echo "scientific notation's fractional portion cannot be negative."
26
return 1
27
fi
28
29
if [ "$fractionalPart" = "" ]; then #测试小数部分是不是为空
30
echo "scientific notation's fractional portion is empty."
31
return 1
32
else
33
if ! validint "$fractionalPart" "" ""; then #测试小数部分是不是整数
34
echo "scientific notation's fractional portion is not integer."
35
return 1
36
fi
37
fi
38
39
if ! validint "$exponent" "" ""; then
40
echo "scientific notation's exponent not integer."
41
return 1
42
fi
43
44
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
最后,整理下书上的,和自己写的:
01
#!/bin/sh
02
03
source validint.sh
04
05
validfloat()
06
{
07
fvalue="$1"
08
delimiter="$(echo $fvalue | sed 's/[^e|^E]//g')"
09
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