jqを使用して、 "Media"属性(.session.attributeListの下)に "node7000"文字列を含むブロックの "name"値を取得したいと思います(例では、jsonの最初の配列ブロックが一致します。2つあります)。一致:
"値": "ノード 7000"
"value": "node7000 および node8000"
予想されるjq出力は次のとおりです。
「17200駅」
[{
"name": "Station 17200",
"attributes": [{
"name": "EnableLog",
"value": "1"
}, {
"name": "LogFont",
"value": "0"
}, {
"name": "IdleTimer",
"value": "30"
}
],
"session": [{
"attributeList": [{
"name": "Launch",
"value": "1"
}, {
"name": "Media",
"value": "node7000"
}
]
}, {
"attributeList": [{
"name": "Group",
"value": "1"
}, {
"name": "RMedia",
"value": "1"
}
]
}, {
"attributeList": [{
"name": "Launch",
"value": ""
}, {
"name": "Media",
"value": "node7000 and node8000"
}
]
}
]
},
{
"name": "Station 17300",
"attributes": [{
"name": "EnableLog",
"value": "1"
}, {
"name": "LogFont",
"value": "0"
}, {
"name": "IdleTimer",
"value": "30"
}
],
"session": [{
"attributeList": [{
"name": "Launch",
"value": "1"
}, {
"name": "Media",
"value": "node6000"
}
]
}, {
"attributeList": [{
"name": "Group",
"value": "1"
}, {
"name": "RMedia",
"value": "1"
}
]
}, {
"attributeList": [{
"name": "Launch",
"value": ""
}, {
"name": "Media",
"value": "node6001"
}
]
}
]
}]
答え1
jq
解決策:
jq '.[] | select([.session[].attributeList[]
| .name == "Media" and (.value | contains("node7000"))
] | any ).name' jsonfile
.[]
- 入力配列のすべての要素(オブジェクト)を繰り返します。select(<condition>)
<condition>
- この入力が返されると、関数は入力を変更せずtrue
、そうでなければ出力を生成しません。contains(element)
- フィルタ生成が入力に完全に含まれているtrue
かどうかelement
any
true
- 配列の要素が次の場合、フィルタはブール値配列を入力として使用します。true
出力:
"Station 17200"
答え2
これは、書き換える方法を示すためのものです。jq
RomanPerekhrestが提案した表現〜する関数any(generator; condition)
型any
使用:
.[] |
select(
any(
.session[].attributeList[];
.name == "Media" and (.value | contains("node7000"))
)
).name
これは、最上位配列の各要素からすべての値を抽出するように関数に指示しますany
。次に、各要素に対して与えられた条件式を使用して、これらの要素から.session[].attributeList[]
ブール配列を作成します。attributeList
ブール値がある場合本物を選択し、最上位配列の対応する要素を選択します。name
次に、キー値を抽出して印刷します。
node7000
明らかに、クエリ文字列がシェル変数に依存するようにするには、次を使用して--arg
式に渡す必要があります。
query_string=node7000
jq --arg media "$query_string" '.[] | select(any(.session[].attributeList[]; .name == "Media" and (.value | contains($media)))).name' file.json
PCREに文字列の代わりに正規表現を渡すには、にcontains($media)
変更します。test($media)
これにより、たとえば、node7000
単語境界記号(\b
)を使用して、偽の正の部分文字列と文字列の一致のリスクを回避できますnode70001
。
jq --arg media '\bnode7000\b' '.[] | select(any(.session[].attributeList[]; .name == "Media" and (.value | test($media)))).name' file.json