我想打印 a 的每个路径和值json逐行包含键值的文件。鉴于以下情况json和杰克,是否也可以添加每行的值?如果不使用杰克还有别的办法吗?我在想一些类似于snmpwalk为了json。另外,对于我想要做的事情有一个技术术语吗?
$ cat short.json | jq '.'
{
"Reservations": [
{
"Groups": [],
"Instances": [
{
"ImageId": "ami-a",
"InstanceId": "i-a",
"InstanceType": "t2.micro",
"KeyName": "ubuntu"
}
]
}
]
}
$ cat short.json | jq -r '[paths | map(.|tostring) | join(".")]'
[
"Reservations",
"Reservations.0",
"Reservations.0.Groups",
"Reservations.0.Instances",
"Reservations.0.Instances.0",
"Reservations.0.Instances.0.ImageId",
"Reservations.0.Instances.0.InstanceId",
"Reservations.0.Instances.0.InstanceType",
"Reservations.0.Instances.0.KeyName"
]
多行输出中的单行示例:
"Reservations.0.Instances.0.ImageId": "ami-a",
如果输出可以格式化以用于以下用途,那就太好了杰克使用复制和粘贴,可以使用 linux cut 轻松分离值:
'.Reservations[].Instances[].ImageId': "ami-a"
$ cat short.json | jq -r '.Reservations[].Instances[].ImageId'
ami-a
答案1
我对此不太了解,jq
但我在互联网上发现了这一点,我认为它适用于您的情况:
剪切和粘贴版本:
jq -r 'paths(scalars | true) as $p | [ ( [ $p[] | tostring ] | join(".") ), ( getpath($p) | tojson )] | join(": ")' short.json
易于阅读的版本:
jq -r '
paths(scalars | true) as $p
| [ ( [ $p[] | tostring ] | join(".") )
, ( getpath($p) | tojson )
]
| join(": ")
' short.json
结果:
Reservations.0.Instances.0.ImageId: "ami-a"
Reservations.0.Instances.0.InstanceId: "i-a"
Reservations.0.Instances.0.InstanceType: "t2.micro"
Reservations.0.Instances.0.KeyName: "ubuntu"
因为我想要奖励积分,所以sed
你可以使用以下技巧来获得你想要的输出:
... | sed "s/^/\'./; s/:/\':/; s/\.0/[]/g"
哪个输出:
'.Reservations[].Instances[].ImageId': "ami-a"
'.Reservations[].Instances[].InstanceId': "i-a"
'.Reservations[].Instances[].InstanceType': "t2.micro"
'.Reservations[].Instances[].KeyName': "ubuntu"
答案2
使用以下jq
表达式,我们确保输出的键和值部分都是有效的 JSON(如果是字符串,则进行编码并加引号;如果是布尔值、数字或 则不加引号null
)。我创建了一个辅助函数kv_to_str
来格式化键值字符串,只是为了便于阅读:
def kv_to_str($k; $v): "\($k): \($v)";
paths(scalars | true) as $p |
kv_to_str(
$p | join(".") | tojson;
getpath($p) | tojson
)
对您的数据进行测试:
$ jq -r 'def kv_to_str($k;$v): "\($k): \($v)"; paths(scalars|true) as $p | kv_to_str($p|join(".")|tojson; getpath($p)|tojson)' file
"Reservations.0.Instances.0.ImageId": "ami-a"
"Reservations.0.Instances.0.InstanceId": "i-a"
"Reservations.0.Instances.0.InstanceType": "t2.micro"
"Reservations.0.Instances.0.KeyName": "ubuntu"
为了获得可用作jq
查询每个值的表达式的内容,我们可以进行一些较小的调整,这样就不用像"Reservations.0.Instances.0.ImageId"
我们那样创建键了.["Reservations"][0]["Instances"][0]["ImageId"]
。请注意,我们将零保留在那里,这使我们能够为数组元素生成更具体的键。
def kv_to_str($k; $v): "\($k): \($v)";
paths(scalars | true) as $p |
kv_to_str(
"." + ($p | map([.] | tojson) | join(""));
getpath($p) | tojson
)
密钥是通过获取路径的每个部分、将其放入[...]
并将其转换为 JSON 来生成的(字符串将被加引号,而整数索引将保持不加引号)。然后我们将各个部分连接起来并在前面添加一个点。
测试:
$ jq -r 'def kv_to_str($k;$v): "\($k): \($v)"; paths(scalars|true) as $p | kv_to_str("." + ($p|map([.]|tojson)|join("")); getpath($p)|tojson)' file
.["Reservations"][0]["Instances"][0]["ImageId"]: "ami-a"
.["Reservations"][0]["Instances"][0]["InstanceId"]: "i-a"
.["Reservations"][0]["Instances"][0]["InstanceType"]: "t2.micro"
.["Reservations"][0]["Instances"][0]["KeyName"]: "ubuntu"
$ jq -r '.["Reservations"][0]["Instances"][0]["InstanceType"]' file
t2.micro