In jq, how to get tonumber to output decimal instead of scientific notation
Unfortunately there is currently no way in jq to modify the representation of JSON numbers as such; the best one can do is modify their representation as strings. Here is a simple illustration of what can be done.
to_decimal
takes as input a JSON number (or a valid JSON string representation of a number, possibly with a leading "+") as input, and converts it into a suitable string, e.g.:
["0","1","-1","123","-123",".00000123","1230000","-.00000123","-0.123","0.123","0.001"]
produces:
[0,"0"]["+1","1"][-1,"-1"][123,"123"][-123,"-123"][1.23e-06,".00000123"][1230000,"1230000"][-1.23e-06,"-.00000123"][-0.123,"-0.123"][0.123,"0.123"][0.001,"0.001"]
Notice that any leading "+" is dropped.
to_decimal
def to_decimal: def rpad(n): if (n > length) then . + ((n - length) * "0") else . end; def lpad(n): if (n > length) then ((n - length) * "0") + . else . end; tostring | . as $s | capture( "(?<sgn>[+-]?)(?<left>[0-9]*)(?<p>\\.?)(?<right>[0-9]*)(?<e>[Ee]?)(?<exp>[+-]?[0-9]+)" ) | if .e == "" then (if .sgn == "+" then $s[1:] else $s end) else (.left|length) as $len | (.exp|tonumber) as $exp | (if .sgn == "-" then "-" else "" end ) as $sgn | if $exp < 0 then "." + (.left | lpad(1 - $exp - $len)) + .right else (.left | rpad($exp - $len)) + "." + .right end | $sgn + . end ;