又是一个jq问题,如何根据子节点的某些条件有效地替换节点值?
根据Syft工具在debian上生成的CycloneDX格式的json: bullet -slim和alpine docker图像
{
"bomFormat": "CycloneDX",
"components": [{
"name": "bsdutils",
"version": "1:2.36.1-8+deb11u1",
"purl": "pkg:deb/debian/bsdutils@1:2.36.1-8+deb11u1?arch=amd64&upstream=util-linux%402.36.1-8+deb11u1&distro=debian-11",
"properties": [{
"name": "syft:metadata:source",
"value": "util-linux"
}, {
"name": "syft:metadata:sourceVersion",
"value": "2.36.1-8+deb11u1"
}
]
}, {
"name": "curl",
"version": "7.74.0-1.3+deb11u7",
"purl": "pkg:deb/debian/curl@7.74.0-1.3+deb11u7?arch=amd64&distro=debian-11"
}, {
"name": "libaudit-common",
"version": "1:3.0-2",
"purl": "pkg:deb/debian/libaudit-common@1:3.0-2?arch=all&upstream=audit&distro=debian-11",
"properties": [{
"name": "syft:metadata:source",
"value": "audit"
}
]
}, {
"name": "busybox-binsh",
"version": "1.35.0-r29",
"purl": "pkg:apk/alpine/busybox-binsh@1.35.0-r29?arch=x86_64&upstream=busybox&distro=alpine-3.17.2",
"properties": [{
"name": "syft:metadata:originPackage",
"value": "busybox"
}
]
}
]
}
我正在寻找最好的jq cmd来给出这个期望的输出:
{
"bomFormat": "CycloneDX",
"components": [{
"name": "util-linux",
"version": "2.36.1-8+deb11u1",
"purl": "pkg:deb/debian/util-linux@2.36.1-8+deb11u1?arch=source",
"properties": [{
"name": "syft:metadata:source",
"value": "util-linux"
}, {
"name": "syft:metadata:sourceVersion",
"value": "2.36.1-8+deb11u1"
}
]
}, {
"name": "curl",
"version": "7.74.0-1.3+deb11u7",
"purl": "pkg:deb/debian/curl@7.74.0-1.3+deb11u7?arch=amd64&distro=debian-11"
}, {
"name": "audit",
"version": "1:3.0-2",
"purl": "pkg:deb/debian/audit@1:3.0-2?arch=source",
"properties": [{
"name": "syft:metadata:source",
"value": "audit"
}
]
}, {
"name": "busybox-binsh",
"version": "1.35.0-r29",
"purl": "pkg:apk/alpine/busybox@1.35.0-r29?arch=source",
"properties": [{
"name": "syft:metadata:originPackage",
"value": "busybox"
}
]
}
]
}
我首先只使用了debian端,并询问了关于遍查元数据的问题,因此从knittl那里得到了这个强大的答案,它正确地回答了我最初的问题。谢谢!
"syft:metadata:source" as $srcName | "syft:metadata:sourceVersion" as $srcVersion
|.components[]
|= . + ( (
.version as $componentVersion
| .properties//[]
| from_entries
| select(has($srcName))
| (.[$srcVersion]//$componentVersion) as $version
| .[$srcName] as $name
| { $name, $version, purl: "pkg:deb/debian/($name)@($version)?arch=source" }
) // {}
)
但是随着alpine的额外输出,这个CMD不再正确。我需要通过purl的'upstream='部分来提取srcName和srcVersion。
并通过保持开始直到@之前的/来重建purl。
.components[].purl | match("/[a-z]+@").offset
给了我第一部分的索引,但我怎么得到之前的字符串呢?
然后我需要提取"upstream="后面的字符串,例如from
上游= util-linux % 402.36.1-8 + deb11u1&
util-linux as $srcName2.36.1-8+deb11u1作为$srcVersion,在跳过'%40'(@)之后,在下一个'&'之前
我如何把所有的东西组合起来?
您可以使用[splits("[=&]|%40")] | .[0,1]
从URL中拆分和提取第二和第三个元素。
将数组元素绑定到变量允许您稍后在程序中使用它们:
printf '"upstream=util-linux%402.36.1-8+deb11u1&"n' | jq '
[splits("[=&]|%40")] as [$upstream, $srcName, $srcVersion]
| { $srcName, $srcVersion }
'
或者,使用capture
使用正则表达式提取对象:
capture("upstream=(?<srcName>.*)%40(?<srcVersion>[^&]*)&")