Commifying Numbers
Problem
You’d like to add a thousands-place separator to long numbers.
Solution
Depending on your system and configuration, you may be able to use printf’s ' format flag with a suitable local. Thanks to Chet Ramey for this solution, which is by far the easiest if it works:
$ LC_NUMERIC=en_US.UTF-8 printf "%'d\n" 123456789 123,456,789 $ LC_NUMERIC=en_US.UTF-8 printf "%'f\n" 123456789.987 123,456,789.987000
Thanks to Michael Wang for contributing the following shell-only implementation and relevant discussion:
# cookbook filename: func_commify
function commify {
typeset text=${1}
typeset bdot=${text%%.*}
typeset adot=${text#${bdot}}
typeset i commified
(( i = ${#bdot} - 1 ))
while (( i>=3 )) && [[ ${bdot:i-3:1} == [0-9] ]]; do
commified=",${bdot:i-2:3}${commified}"
(( i -= 3 ))
done
echo "${bdot:0:i+1}${commified}${adot}"
}Or you can try one of the sed solutions from the sed FAQ, for example:
sed ':a;s/\B[0-9]\{3\}\>/,&/;ta' /path/to/file # GNU sed
sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta' /path/to/file # other sedsDiscussion
The shell function is written to follow the same logical process as a person using a pencil and paper. First you examine the string and find the decimal point, if any. You ignore everything after the dot, and work on the string before the dot.
The shell function saves the string before the dot in $bdot, and after the dot (including the dot)
in $adot. If there is no dot, then
everything is in $bdot, and $adot is empty. Next a person would ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access