특정 속성을 가진 객체를 검색한 후 다른 속성을 업데이트하려고 합니다. 다음 입력이 주어지면:
[
{
"replacements": [
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.abc.image.tag"
},
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.def.image.tag"
},
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.ghi.image.tag"
}
],
"yamlFilePath": "k8s/helm/Dev/us-east-1/values.yaml"
}
]
그리고 자리 표시자( abc-image-tag
for k8s-helm-templates.deployment.containers.abc.image.tag
)를 다음과 같이 사용합니다.
[
{"name":"abc-image-tag","value":"123"},
{"name":"def-image-tag","value":"456"}
]
당신이 얻어야 할 것은 주어진 값이 올바르게 대체되고 0 값이 다음과 같이 필터링된다는 것입니다.
[
{
"replacements": [
{
"newValue": "123",
"yamlPath": "k8s-helm-templates.deployment.containers.abc.image.tag"
},
{
"newValue": "456",
"yamlPath": "k8s-helm-templates.deployment.containers.def.image.tag"
}
],
"yamlFilePath": "k8s/helm/Dev/us-east-1/values.yaml"
}
]
몇 가지 트릭을 시도하고 문서를 조사했지만 제대로 작동하지 않는 것 같습니다. jq로 가능할까요? 다른 단계를 수행하려면 bash를 사용하세요.
답변1
이 시도:
jq \
--null-input \
--rawfile replacements replacements.json \
--rawfile placeholders placeholders.json \
'
def placeholder_index: .name | gsub("-"; ".") ;
def replacement_index: .yamlPath | sub("^k8s-helm-templates\\.deployment\\.containers\\."; "") ;
def replace($placeholders):
[
JOIN(INDEX(.[]; replacement_index); $placeholders[]; placeholder_index) |
{newvalue: .[0].value, yamlPath: .[1].yamlPath}
]
;
$replacements | fromjson as $replacements |
$placeholders | fromjson as $placeholders |
$replacements | .[0].replacements |= replace($placeholders)
'
이 목표를 달성하기 위해 제가 만든 프로토타입을 보여줌으로써 이를 설명할 수 있습니다.
각 입력이 파일에 있다고 가정합니다.
cat > replacements.json <<"EOF"
[
{
"replacements": [
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.abc.image.tag"
},
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.def.image.tag"
},
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.ghi.image.tag"
}
],
"yamlFilePath": "k8s/helm/Dev/us-east-1/values.yaml"
}
]
EOF
cat > placeholders.json <<"EOF"
[
{"name":"abc-image-tag","value":"123"},
{"name":"def-image-tag","value":"456"}
]
EOF
첫 번째 비결은 각 입력에 대한 핸들을 얻는 것입니다. 입력이 하나만 있는 경우 일반적으로 표준 입력에서 이를 읽고 .
파이프 시작 부분에서 참조합니다. 입력이 여러 개인 경우 --rawfile
각 JSON 텍스트를 명명된 변수에 로드하는 데 사용할 수 있습니다. 명백한 "기본" 입력이 없으면 --null-input
jq를 사용하여 표준 입력에서 읽지 않을 수 있습니다.
--rawfile
문자열을 읽으므로 이를 사용하여 fromjson
JSON 개체를 구문 분석해야 합니다. 를 사용하여 JSON 개체 배열을 읽을 수도 있지만 --slurpfile
첫 번째 요소를 선택해야 하므로 여전히 추가 단계입니다.
jq \
--null-input \
--rawfile replacements replacements.json \
--rawfile placeholders placeholders.json \
'
$replacements | fromjson as $replacements |
$placeholders | fromjson as $placeholders |
$replacements, $placeholders
'
원하는 결과는 두 SQL 데이터베이스 테이블 간의 내부 조인처럼 보입니다. jq에는 유사한 작업을 수행할 수 있는 "SQL 스타일 연산자"가 있기 때문에 이렇게 말하는 것입니다. 문서화가 잘 안 되어 있어서 여기에서 시행착오를 거쳐 알아냈습니다.
INDEX
입력 스트림의 각 개체를 키에 매핑하고 JOIN
두 인덱스에 대해 내부 조인을 수행하는 개체를 생성하는 데 사용됩니다 .
인덱스는 $replacements
이렇게 생겼습니다. 여기의 키 표현식은 공통 접두사를 제거하여 yamlPath
변경 가능한 이미지 태그를 남깁니다.
jq \
--null-input \
--rawfile replacements replacements.json \
--rawfile placeholders placeholders.json \
'
$replacements | fromjson as $replacements |
$placeholders | fromjson as $placeholders |
INDEX(
$replacements[0].replacements[];
.yamlPath | sub("^k8s-helm-templates\\.deployment\\.containers\\."; "")
)
'
{
"abc.image.tag": {
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.abc.image.tag"
},
"def.image.tag": {
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.def.image.tag"
},
"ghi.image.tag": {
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.ghi.image.tag"
}
}
인덱스는 $placeholders
이렇게 생겼습니다. 키 표현식은 가변 이미지 레이블이 labels 처럼 보이도록 대시를 점으로 바꿉니다 $replacements
.
jq \
--null-input \
--rawfile replacements replacements.json \
--rawfile placeholders placeholders.json \
'
$replacements | fromjson as $replacements |
$placeholders | fromjson as $placeholders |
INDEX($placeholders[]; .name | gsub("-"; "."))
'
{
"abc.image.tag": {
"name": "abc-image-tag",
"value": "123"
},
"def.image.tag": {
"name": "def-image-tag",
"value": "456"
}
}
두 인덱스 개체의 일부 키가 일치하는 것을 볼 수 있습니다. 이것이 우리가 JOIN
이러한 객체의 내부 연결을 수행하는 기능을 얻는 방법입니다.
실제로 이 함수는 어쨌든 두 번째 인덱스를 효과적으로 생성하므로 INDEX
한 번만 호출하면 됩니다 .JOIN
JOIN
첫 번째 개체는 스트림 입력에서 가져오고 두 번째 개체는 인덱스 입력에서 가져오는 쌍 목록의 스트림을 반환합니다.
jq \
--null-input \
--rawfile replacements replacements.json \
--rawfile placeholders placeholders.json \
'
$replacements | fromjson as $replacements |
$placeholders | fromjson as $placeholders |
JOIN(
INDEX(
$replacements[0].replacements[];
.yamlPath | sub("^k8s-helm-templates\\.deployment\\.containers\\."; "")
);
$placeholders[];
.name | gsub("-"; ".")
)
'
[
{
"name": "abc-image-tag",
"value": "123"
},
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.abc.image.tag"
}
]
[
{
"name": "def-image-tag",
"value": "456"
},
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.def.image.tag"
}
]
다음 단계는 연결된 각 개체에서 올바른 속성을 "선택"하여 새 개체를 만든 다음 출력을 JOIN
배열로 래핑하는 새 개체를 만드는 것입니다.
jq \
--null-input \
--rawfile replacements replacements.json \
--rawfile placeholders placeholders.json \
'
$replacements | fromjson as $replacements |
$placeholders | fromjson as $placeholders |
[
JOIN(
INDEX(
$replacements[0].replacements[];
.yamlPath | sub("^k8s-helm-templates\\.deployment\\.containers\\."; "")
);
$placeholders[];
.name | gsub("-"; ".")
) |
{newvalue: .[0].value, yamlPath: .[1].yamlPath}
]
'
[
{
"newvalue": "123",
"yamlPath": "k8s-helm-templates.deployment.containers.abc.image.tag"
},
{
"newvalue": "456",
"yamlPath": "k8s-helm-templates.deployment.containers.def.image.tag"
}
]
최종 솔루션에서는 각 표현식의 이름을 지정하는 몇 가지 함수를 정의했습니다. 업데이트 할당 연산자를 사용하여 |=
원래 구조를 복사 $replacements
하고 조인 결과로 내부 목록을 업데이트합니다.