使用 jq 从 json 生成 "table"
generating "table" from json using jq
从上一个问题中取回我的示例数据之一:
{
"countries": [
{
"countryName": "CZ",
"cities": [
{
"cityName": "Prague",
"streets": [
{
"streetName": "Norská"
},
{
"streetName": "Slovenská"
}
]
}
]
},
{
"countryName": "FR",
"cities": [
{
"cityName": "Paris",
"streets": [
{
"streetName": "rue piat"
},
{
"streetName": "rue lesage"
}
]
}
]
}
]
}
我想使用 jq 从这些数据中生成 plaintext/asciidoc/markdown table,但我想念一些基本的方法。给定列中的重复是我没有得到的。
因此预期的输出可能如下所示:
CZ Prague Norská
CZ Prague Slovenská
FR Paris rue piat
FR Paris rue lesage
即。如何遍历顶级数组 countries
,从中选择字段 countryName
,如何遍历包含在 countries
数组元素中的字段 cities
并从中选择 cityName
等得到三元组的结果数组,然后可以将其处理成所需的输出文本。
编辑:
已更新 json 以与预期的输出数据同步。
同时我还挺幸运的表达:
jq'.国家[] | .countryName 为 $country|城市[] | .cityName 作为 $city |街道[] | $country+" "+$city+" "+.streetName ' < /tmp/sampleData.json
但出于某种原因,以下使用@csv 的方法对我不起作用。
jq '[(.countries[] | .countryName as $country| .cities[] | .cityName as $city | .streets[] | [$country,$city,.streetName])] | @csv' < /tmp/sampleData.json
如果有任何改进建议,我将不胜感激。
EDIT2:要使@csv 工作,它必须用数组(它是)而不是数组数组来提供。对命令式编程风格的误解。无论如何,这个是正确的:
jq '[(.countries[] | .countryName as $country| .cities[] | .cityName as $city | .streets[] | [$country,$city,.streetName])] | .[] | @csv' < /tmp/sampleData.json
可以稍微简化您的 jq 解决方案,同时提高其效率:
.countries[]
| .countryName as $country
| .cities[]
| .cityName as $city
| .streets[]
| [$country, $city, .streetName]
| @csv
结合 -r command-line 选项,这当然会生成有效的 CSV,但您的 Q 表示偏好删除(不必要的?)引号。对于显示的示例数据,您可以将 @csv
替换为 join(",")
,但通常情况下,必须注意 CSV 特有的逗号和其他字符。
一般情况
以下似乎可以处理一般情况,但依赖于 sed 来处理关于引号和嵌入换行符的 CSV 约定,并且尚未经过彻底测试:
< sampleData.json jq -r '
def q:
if type == "string" and test("[,\n\"]")
then tojson
else . end;
.countries[]
| .countryName as $country
| .cities[]
| .cityName as $city
| .streets[]
| [$country, $city, .streetName]
| map(q)
| join(",")
' | sed -e 's/\\"/""/g' -e 's/\n/\
/g'
从上一个问题中取回我的示例数据之一:
{
"countries": [
{
"countryName": "CZ",
"cities": [
{
"cityName": "Prague",
"streets": [
{
"streetName": "Norská"
},
{
"streetName": "Slovenská"
}
]
}
]
},
{
"countryName": "FR",
"cities": [
{
"cityName": "Paris",
"streets": [
{
"streetName": "rue piat"
},
{
"streetName": "rue lesage"
}
]
}
]
}
]
}
我想使用 jq 从这些数据中生成 plaintext/asciidoc/markdown table,但我想念一些基本的方法。给定列中的重复是我没有得到的。
因此预期的输出可能如下所示:
CZ Prague Norská
CZ Prague Slovenská
FR Paris rue piat
FR Paris rue lesage
即。如何遍历顶级数组 countries
,从中选择字段 countryName
,如何遍历包含在 countries
数组元素中的字段 cities
并从中选择 cityName
等得到三元组的结果数组,然后可以将其处理成所需的输出文本。
编辑:
已更新 json 以与预期的输出数据同步。
同时我还挺幸运的表达:
jq'.国家[] | .countryName 为 $country|城市[] | .cityName 作为 $city |街道[] | $country+" "+$city+" "+.streetName ' < /tmp/sampleData.json
但出于某种原因,以下使用@csv 的方法对我不起作用。
jq '[(.countries[] | .countryName as $country| .cities[] | .cityName as $city | .streets[] | [$country,$city,.streetName])] | @csv' < /tmp/sampleData.json
如果有任何改进建议,我将不胜感激。
EDIT2:要使@csv 工作,它必须用数组(它是)而不是数组数组来提供。对命令式编程风格的误解。无论如何,这个是正确的:
jq '[(.countries[] | .countryName as $country| .cities[] | .cityName as $city | .streets[] | [$country,$city,.streetName])] | .[] | @csv' < /tmp/sampleData.json
可以稍微简化您的 jq 解决方案,同时提高其效率:
.countries[]
| .countryName as $country
| .cities[]
| .cityName as $city
| .streets[]
| [$country, $city, .streetName]
| @csv
结合 -r command-line 选项,这当然会生成有效的 CSV,但您的 Q 表示偏好删除(不必要的?)引号。对于显示的示例数据,您可以将 @csv
替换为 join(",")
,但通常情况下,必须注意 CSV 特有的逗号和其他字符。
一般情况
以下似乎可以处理一般情况,但依赖于 sed 来处理关于引号和嵌入换行符的 CSV 约定,并且尚未经过彻底测试:
< sampleData.json jq -r '
def q:
if type == "string" and test("[,\n\"]")
then tojson
else . end;
.countries[]
| .countryName as $country
| .cities[]
| .cityName as $city
| .streets[]
| [$country, $city, .streetName]
| map(q)
| join(",")
' | sed -e 's/\\"/""/g' -e 's/\n/\
/g'