![如何循环遍历json文件?](https://linux22.com/image/88950/%E5%A6%82%E4%BD%95%E5%BE%AA%E7%8E%AF%E9%81%8D%E5%8E%86json%E6%96%87%E4%BB%B6%EF%BC%9F.png)
我有一个下面的 json 文件,我想获取 hostId,前提是该文件name
包含某些特定值。我想使用shell脚本来实现这一点。
{
"items" : [ {
"name" : "first-block-e70a2fe8fd0531ad1f87de49f03537a6",
"type" : "STORE",
"hostRef" : {
"hostId" : "166219e3-be5c-46d0-b4c7-33543a29ce32"
},
"roleState" : "STARTED",
"healthSummary" : "GOOD",
},
{
"name" : "second-block-c21a1ae8dd2831cd1b87de49f98274e8",
"type" : "STORE",
"hostRef" : {
"hostId" : "176429e3-be5c-46d0-b4c7-33543a29ad63"
},
"roleState" : "STARTED",
"healthSummary" : "GOOD",
}
{
"name" : "first-block-a85d2fe6fd0482ad1f54de49f45174a0",
"type" : "STORE",
"hostRef" : {
"hostId" : "176429e3-ae1d-46d0-b4c7-66123a24fa82"
},
"roleState" : "STARTED",
"healthSummary" : "GOOD",
}
}
例如:如果名称包含“first-block”的内容,那么我应该将 hosdId 获取为
166219e3-be5c-46d0-b4c7-33543a29ce32
176429e3-ae1d-46d0-b4c7-66123a24fa82
如何迭代 json 文件?我应该使用什么正则表达式来过滤包含某些特定值的元素name
并获取hostid
?
答案1
你可以使用 jq:
输入文件:
{
"items" : [
{
"name" : "first-block-e70a2fe8fd0531ad1f87de49f03537a6",
"type" : "STORE",
"hostRef" : {
"hostId" : "166219e3-be5c-46d0-b4c7-33543a29ce32"
},
"roleState" : "STARTED",
"healthSummary" : "GOOD"
},
{
"name" : "second-block-c21a1ae8dd2831cd1b87de49f98274e8",
"type" : "STORE",
"hostRef" : {
"hostId" : "176429e3-be5c-46d0-b4c7-33543a29ad63"
},
"roleState" : "STARTED",
"healthSummary" : "GOOD"
},
{
"name" : "first-block-a85d2fe6fd0482ad1f54de49f45174a0",
"type" : "STORE",
"hostRef" : {
"hostId" : "176429e3-ae1d-46d0-b4c7-66123a24fa82"
},
"roleState" : "STARTED",
"healthSummary" : "GOOD"
}
]
}
命令:
编辑:与 @Runium 的贡献
$ jq '.items[] | select( .name | startswith("first-block-"))|.hostRef.hostId' < file.json
"e70a2fe8fd0531ad1f87de49f03537a6"
"a85d2fe6fd0482ad1f54de49f45174a0"
答案2
使用 python 的一个非常简单的示例:
#!/usr/bin/env python
import sys
import json
def print_first(data):
for item in data["items"]:
if item["name"].startswith("first"):
print item["hostRef"]["hostId"]
def main(argv):
for json_file in argv:
with open(json_file) as data_file:
data = json.load(data_file)
print_first(data)
if __name__ == "__main__":
main(sys.argv[1:])
即您的示例数据重新格式化为:
{
"items" : [
{
"name" : "first-block-e70a2fe8fd0531ad1f87de49f03537a6",
"type" : "STORE",
"hostRef" : {
"hostId" : "166219e3-be5c-46d0-b4c7-33543a29ce32"
},
"roleState" : "STARTED",
"healthSummary" : "GOOD"
},
{
"name" : "second-block-c21a1ae8dd2831cd1b87de49f98274e8",
"type" : "STORE",
"hostRef" : {
"hostId" : "176429e3-be5c-46d0-b4c7-33543a29ad63"
},
"roleState" : "STARTED",
"healthSummary" : "GOOD"
},
{
"name" : "first-block-a85d2fe6fd0482ad1f54de49f45174a0",
"type" : "STORE",
"hostRef" : {
"hostId" : "176429e3-ae1d-46d0-b4c7-66123a24fa82"
},
"roleState" : "STARTED",
"healthSummary" : "GOOD"
}
]
}
答案3
正如@Theophrastus 提到的,您需要jq
首先安装 JSON 解析器。之后,只需过滤您想要的值即可。
我应该提到的是,您发布的 JSON 块无效; “items”的左括号未闭合,第二个条目items
应有逗号分隔符。尽管如此,我还是假设您有一个有效的块,并且只剪切并粘贴您认为相关的内容。如果每个块确实具有代表性,那么您需要添加的是(假设bash
是您的 shell)
echo "${YOUR_JSON_BLOCK}" | jq '.items[].hostRef.hostId'
假设 YOUR_JSON_BLOCK 是包含数据的完整有效 json 字符串,这将按照指定输出这些行。
答案4
最近我想出了一个更简单的 unix/shell 替代方案(它完全是 FOSS 并且免费)来处理这样的 json 查询 - 看看jtc
。该工具可以处理相对行走(即找到一个然后偏移到另一个)。
假设您的原始 json 已修复(它有几个问题),那么 cli 将如下所示:
bash $ cat file.json | jtc -w'[name]:<^first-block>R: [-1] [hostRef] [hostId]'
"166219e3-be5c-46d0-b4c7-33543a29ce32"
"176429e3-ae1d-46d0-b4c7-66123a24fa82"
bash $