直接显示未格式化的计算结果是程序员常犯的错误。如果我们沒有将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 |