我有一個下面的 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 $