You can expand a bit and take the great answer by @anubhava a bit further by allowing the width on both the real-part and fractional-part to be set and fully validating the input and handling any errors in your function. The approach though is the same, using the printf
format string is key.
For example your function can take the floating-point number as the first argument, the width of the real-part as the second, and optionally take the width of the fractional-part as the third, e.g.
#!/bin/bash
formatfloat () {
[ -z "$1" -o -z "$2" ] && { ## validate at least 2 arguments given
printf "error: formatfloat() insufficient arguments.\n" >&2
printf "usage: formatfloat() float width_real [width_fract]\n" >&2
return 1;
}
[[ $1 =~ ^-*[[:digit:]]*[.][[:digit:]]* ]] || { ## validate float
printf "error: formatfloat() not a valid floating point number.\n" >&2
return 1
}
[ "$2" -eq "$2" > /dev/null ] || { ## validate width is an integer
printf "error: formatfloat() width_real not an integer.\n" >&2
return 1
}
local realpart="${1%.*}" ## parameter expansion separates real/fraction parts
local fractpart="${1#*.}"
local width_real="$2"
if [ -n "$3" ]; then ## if fractional part width given
[ "$3" -eq "$3" > /dev/null ] || { ## validate it is an integer
printf "error: formatfloat() width_fract not an integer.\n" >&2
return 1
}
local width_fract="$3" ## output setting both widths
local fppad="$((width_fract - ${#fractpart}))" ## needed fract part rt-pad
[ "$fppad" -le 0 ] && { ## no padding needed
printf "%0*d.%d\n" $width_real $realpart $fractpart
return 0
}
for ((i = 0; i < fppad; i++)); do ## add padding to fract part
fractpart="${fractpart}0"
done
printf "%0*d.%*d\n" $width_real $realpart $width_fract $fractpart
else ## output setting real-part width
printf "%0*d.%d\n" $width_real $realpart $fractpart
fi
return 0
}
A short example with your data could be:
printf "A (Current) B (Desired)\n----- ------\n"
for n in 8.456 4.19 3.5; do
printf "%-14s%s\n" "$n" "$(formatfloat "$n" 2)"
done
Output
$ bash formatfloat.sh
A (Current) B (Desired)
----- ------
8.456 08.456
4.19 04.19
3.5 03.5
Setting Width of Both
for n in 8.456 4.19 3.5; do
printf "%-14s%s\n" "$n" "$(formatfloat "$n" 2 3)"
done
Output
$ bash formatfloat.sh
A (Current) B (Desired)
----- ------
8.456 08.456
4.19 04.190
3.5 03.500