提问人:mackermann 提问时间:10/27/2023 更新时间:11/8/2023 访问量:63
jq - 在 JSON 文件的任何级别搜索字符串值并获取父键
jq - search a string value at any level of a json file and get the parent keys
问:
我想在JSON文件中找到JSON文件的任何级别的特定值(而不用担心键)(我事先不知道确切的树)并显示父键。
我已经提取了这个样本:
cat /tmp/test.json | jq
{
"totalCount": 2,
"pageSize": 1000,
"auditLogs": [
{
"logId": "169807591200060002",
"eventType": "CREATE",
"category": "CONFIG",
"entityId": "HTTP_CHECK-12121212121212",
"timestamp": 1698075912003,
"success": true,
"patch": [
{
"op": "replace",
"path": "/",
"value": {
"steps": [
{
"id": {
"type": "HTTP_CHECK_STEP"
},
"requestType": "OAUTH2",
"destinationUrl": "https://www.mywebsite.com",
"httpMethod": "POST",
"acceptAnyCertificate": true,
"followRedirects": true,
"displayName": "My Website",
"userAgent": "",
"httpCheckHeaders": [
{
"name": "Content-Type",
"value": "application/x-www-form-urlencoded"
}
],
"stepPerformanceThreshold": 0,
"requestBody": null,
"constraints": [
{
"constraintType": "HttpStatusesList",
"passIfFound": false,
"pattern": ">=400"
}
],
"preScript": "",
"postScript": "",
"attributes": {
"oAuth2RequestId": "1",
"oAuth2BodyInputType": "RAW",
"oAuth2addAuthDataTo": "REQUEST_BODY"
},
"postExecutionScriptVariables": [
"{bearerToken-1}"
],
"preExecutionScriptVariables": [],
"certificateId": "",
"basicAuthId": "",
"certStoreId": 0,
"basicAuthStoreId": 0,
"authenticationConfig": {
"type": "BASIC_AUTHENTICATION",
"realmName": null,
"kdcIp": null,
"credentialId": "CREDENTIALS_VAULT-1212121212121"
},
"executionProperties": {},
"shouldNotPersistSensitiveData": true
}
],
"publicLocationIds": [
124
],
"userModificationTimestamp": 1698075911987,
"customProperties": [],
"version": 6
},
"oldValue": null
}
]
},
{
"logId": "169807591200060001",
"eventType": "CREATE",
"category": "CONFIG",
"entityId": "HTTP_CHECK-12121212121212",
"environmentId": "b416bf43-a9d2-4123-aa70-e36ff39c0ad9",
"timestamp": 1698075911986,
"success": true,
"patch": [
{
"op": "replace",
"path": "/",
"value": {
"frequency (Frequency)": 0,
"locations": [
{
"location (Location)": "SYNTHETIC_LOCATION-000000000000007C"
}
]
},
"oldValue": null
}
]
}
]
}
我能够使用此递归命令找到字符串“CREDENTIALS_VAULT-1212121212121”:
cat /tmp/test.json | jq '.auditLogs[] | .. | .credentialId? | select(. == "CREDENTIALS_VAULT-1212121212121")'
"CREDENTIALS_VAULT-1212121212121"
但我还想在第一级获取父键“logId”。我尝试使用变量($parent),但不幸的是,我得到了几个结果,而不仅仅是一个:
cat /tmp/test.json | jq '.auditLogs[] as $parent | .. | .credentialId? | select(. == "CREDENTIALS_VAULT-1212121212121") | $parent | {"logId":.logId}'
{
"logId": "169807591200060002"
}
{
"logId": "169807591200060001"
}
有人对这种需求有想法吗?
答:
1赞
pmf
10/27/2023
#1
您可以使用查找具有匹配值的路径,从中提取前两项(在本例中),用于检索该对象,然后从那里提取:paths
["auditLogs",0]
getpath
.logId
jq -r 'getpath(paths(. == "CREDENTIALS_VAULT-1212121212121")[:2]).logId'
169807591200060002
如果希望对象仅包含字段,请改用:logId
{logId}
jq 'getpath(paths(. == "CREDENTIALS_VAULT-1212121212121")[:2]) | {logId}'
{
"logId": "169807591200060002"
}
还可以考虑通过环绕筛选器来将结果收集到数组中。或者使用该选项从命令行导入搜索键等。[…]
--arg
0赞
knittl
10/27/2023
#2
您可以使用 IN
(或):any(stream; condition)
.auditLogs[]
| select(IN(.. | .credentialId?; "CREDENTIALS_VAULT-1212121212121"))
| .logId
或者,根据您的输出格式要求:
.auditLogs[]
| select(IN(.. | .credentialId?; "CREDENTIALS_VAULT-1212121212121"))
| { logId }
1赞
peak
10/28/2023
#3
...不用担心钥匙
...我事先不知道确切的树
这是一种满足这两个要求的简单方法(我认为比使用和更快):paths
getpath
.. | objects
| select(.logId)
| .logId as $id
| .. | objects
| select(.[] == "CREDENTIALS_VAULT-1212121212121")
| $id
由于该字符串可能会出现多次,因此您可能需要考虑变体,例如将上面的倒数第二行替换为:
| select(first(.[] == "CREDENTIALS_VAULT-1212121212121" // empty))
0赞
mackermann
11/8/2023
#4
非常感谢您的回答。我最终选择使用 getpath() 函数使用第一个解决方案。使用此解决方案,我们不关心密钥的名称。事实上,在我的情况下,搜索模式(“CREDENTIALS_VAULT-1212121212121”)不是必需的,键“credentialId”的值。这可能是另一个关键:
$ grep "CREDENTIALS_VAULT-1212121212121" auditlogs2.json
"credentialId": "CREDENTIALS_VAULT-1212121212121"
"myotherkey": "CREDENTIALS_VAULT-1212121212121"
$ cat auditlogs2.json | jq -r 'getpath(paths(. == "CREDENTIALS_VAULT-1212121212121")[:2]) | .logId'
169807591200060002
169807591200060001
两个条目都已找到。这在我的情况下更合适;) 但再次感谢每一个人。
评论