分类:
2008-03-21 16:50:41
直接显示未格式化的计算结果是程序员常犯的错误。如果我们沒有将43245435这个数加上一个干分号(数值中每隔三位加上的一个逗号)的话,对使用者而言,他们很难直接读出这个数值的大小。那么请利用下面这个脚本来解決这个问题。
脚本源代码
#!/bin/sh
# nicenumber -- 为加上千分号.
# 如果在数字后有参数,则程序中的DD与TD将会被替代
nicenumber()
{
# 我们假定在这个脚本中使用者输入的小数点符号为"."。
# 如果使用者没有特别利用 -d 的参数,改变输出方式,
# 预设的小数点输出也是"."。
integer=$(echo $1 | cut -d. -f1) # left of the decimal
decimal=$(echo $1 | cut -d. -f2) # right of the decimal
if [ $decimal != $1 ]; then
# There's a fractional part, so let's include it.
result="${DD:="."}$decimal"
fi
thousands=$integer
while [ $thousands -gt 999 ]; do
remainder=$(($thousands % 1000)) # 3个数字为一组
while [ ${#remainder} -lt 3 ] ; do # force leading zeros as needed
remainder="0$remainder"
done
thousands=$(($thousands / 1000)) # to left of remainder, if any
result="${TD:=","}${remainder}${result}" # builds right to left
done
nicenum="${thousands}${result}"
if [ ! -z $2 ] ; then
echo $nicenum
fi
}
DD="." # decimal point delimiter, to separate integer and fractional values
TD="," # thousands delimiter, to separate every three digits
while getopts "d:t:" opt; do
case $opt in
d ) DD="$OPTARG" ;;
t ) TD="$OPTARG" ;;
esac
done
shift $(($OPTIND - 1))
if [ $# -eq 0 ] ; then
echo "Usage: $(basename $0) [-d c] [-t c] numeric value"
echo " -d specifies the decimal point delimiter (default '.')"
echo " -t specifies the thousands delimiter (default ',')"
exit 0
fi
nicenumber $1 1 # second arg forces nicenumber to 'echo' output
exit 0
工作原理
函数nicenumber是整个脚本最重要的部分,它主要的工作是将数值一个个的分离,凑足三个即加一个千份号,并将剩下的部分,反复的做上一个动作,直到全部处理完毕为止。
运行脚本
不管你是使用预设或是有增加参数,请给这个程序一个非常大的数字,程序将视需要帮你添加千份号及小数点,并显示计算结果,如下所示:
echo "Do you really want to pay $(nicenumber $price) dollars?"
结果
$ nicenumber 5894625
5,894,625
$ nicenumber 589462532.433
589,462,532.433
$ nicenumber -d, -t. 589462532.433
589.462.532,433
改进与加强
由于不同的国家在使用千份号及其小数点的表示方式各有不同,因此为了让程序更有弹性,我们增加了一个参数。举例来看德国与意大利使用-d "." 与 -t ",". ,法国使用 -d ","与-t" ",还有四种语言的瑞士使用 -d "."与-t "'"。因为有了这些好的例子,我们可以说:这个具有弹性的程序对于使用者而言,是一个相当实用的工具。另一方面,在程序中我来把输入的小数点固定为 ".",如果需要改变这个预设的符号时,大家可以修改两行程式,修改方式如下:
integer=$(echo $1 | cut "-d$DD" -f1) # 数字的左边
decimal=$(echo $1 | cut "-d$DD" -f2) # 数字的右边
如果大家输入不同的小数点符号,对目前的程序而言,似乎不尽理想。让大家在输入前即可确认小数点符号,应该是理想的做法,因此我们可以在这两行代码前再增加一小段代码,另外,我们也可以增加 #2中的测试程序,剪下需要的程式码即可:
separator="$(echo $1 | sed 's/[[:digit:]]//g')"
if [ ! -z "$separator" -a "$separator" != "$DD" ] ; then
echo "$0: Unknown decimal separator $separator encountered." >&2
exit 1
fi