How do I extract a JSON list into a CSV in command line using JQ?

拜拜、爱过 提交于 2020-08-08 06:39:19

问题


I have the following JSON data:

% cat test2 

{"day":"2020-07-15","map":
{"a":"ask","b":"bid","t":"timestamp"},"msLatency":52,"pair":"EUR/USD","status":"success","ticks":[
{"b":1.14105,"a":1.14106,"x":48,"t":1594771200000},
{"b":1.14105,"a":1.14106,"x":48,"t":1594771201000},
{"b":1.14103,"a":1.14104,"x":48,"t":1594771202000},
{"b":1.141,"a":1.1413,"x":48,"t":1594771203000},
{"b":1.14103,"a":1.14104,"x":48,"t":1594771205000},
{"b":1.14094,"a":1.14095,"x":48,"t":1594778803000}],"type":"forex"}

And I want to get:

1.14105,1.14106,1594771200000
1.14105,1.14106,1594771201000
1.14103,1.14104,1594771202000
1.141,1.1413,1594771203000
1.14103,1.14104,1594771205000
1.14094,1.14095,1594778803000

Ideally the output shall also pad with zeros, with 1 and 5 being parameters to specify that the first two columns are numbers with 1 natural place and 5 decimal places (although this step can be done easily with awk):

1.14105,1.14106,1594771200000
1.14105,1.14106,1594771201000
1.14103,1.14104,1594771202000
1.14100,1.14130,1594771203000
1.14103,1.14104,1594771205000
1.14094,1.14095,1594778803000

I have tried this with JQ:

 % cat test2 | jq '.ticks'
[
  {
    "b": 1.14105,
    "a": 1.14106,
    "x": 48,
    "t": 1594771200000
  },
  {
    "b": 1.14105,
    "a": 1.14106,
    "x": 48,
    "t": 1594771201000
  },
  {
    "b": 1.14103,
    "a": 1.14104,
    "x": 48,
    "t": 1594771202000
  },
  {
    "b": 1.141,
    "a": 1.1413,
    "x": 48,
    "t": 1594771203000
  },
  {
    "b": 1.14103,
    "a": 1.14104,
    "x": 48,
    "t": 1594771205000
  },
  {
    "b": 1.14094,
    "a": 1.14095,
    "x": 48,
    "t": 1594778803000
  }
]

But I am stuck on how to turn this into a CSV.

EDIT: Just as reference, I previously had the following parsing, using JQ here is much simpler option:

cat test2 |
sed -e 's/{\"/#{\"/g' |
tr '#' '\n' |
grep -v "timestamp" |
grep -v "day" |
sed '/^[[:space:]]*$/d' |
sed 's/].*$//g' |
sed 's/{//g' |
sed 's/},//g' |
sed 's/}//g' |
sed 's/\"//g' |
awk -F '[:,]' -v decimal_places=5 -v integer_places=1 '{
        for(i=1; i<=NF; i=i+2) {
                value[$i]=$(i+1);
        };
        format_price="%0" integer_places "." decimal_places "f"
        format=format_price " " format_price " %d\n"
        printf(format,value["b"],value["a"],value["t"]);
}'

回答1:


Here's a solution:

jq -r '.ticks[] | [.b, .a, .t] | join(",")' test2

1.14105,1.14106,1594771200000
1.14105,1.14106,1594771201000
1.14103,1.14104,1594771202000
1.141,1.1413,1594771203000
1.14103,1.14104,1594771205000
1.14094,1.14095,1594778803000

It doesn't do the padding to 5 digits. I have no idea how to do that in jq. I still think another language would be easier.




回答2:


Here's an idiomatic jq-only solution to the problem, understood to require that the number of digits to the right of a decimal point, if present, be as specified. The -r command-line option should be used.

# format numbers whose tostring representation has a decimal point
# so that the number of digits to the right of the decimal point is $dd
# assuming $dd >= 0
def format($dd):
  def rpad: (. + $dd * "0") | .[:$dd];
  tostring
  | index(".") as $dec
  | if $dec then .[0:$dec+1] + (.[$dec+1:]|rpad)
    else .
    end ;

.ticks[]
| [(.b | format(1)), (.a | format(5)), .t ]
| join(",")



回答3:


You can very well write your own padding function for this. First extract the number of digits following the decimal digit and decide on the padding digits accordingly.

You can put together a script, name it script.jq and do below. Note that the logic below will not work for numbers in scientific notation.

#!/usr/bin/jq -f

def pad($len): 
  tostring | 
  match("^([0-9]*).([0-9]+)$").captures[1].length as $dec |
  ($len - $dec) as $l  |
  . + ("0" * ($l)) [:$l];

.ticks[] | [ (.b|pad(5)), (.a|pad(5)), .t ] | join(",")

and call it with the jq executable

jq -r -f script.jq json

which now produces a properly padded output

1.14105,1.14106,1594771200000
1.14105,1.14106,1594771201000
1.14103,1.14104,1594771202000
1.14100,1.14130,1594771203000
1.14103,1.14104,1594771205000
1.14094,1.14095,1594778803000

Note: The pad($len) is inspired from pkoppstein's comment from stedolan/jq - pad function #2033



来源:https://stackoverflow.com/questions/62938833/how-do-i-extract-a-json-list-into-a-csv-in-command-line-using-jq

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!