Есть файл sample.yaml
---
action: "want-to-update"
foo: |-
{
"a" : "actual A",
"b" : "actual B",
"c" : "actual C"
}
---
action: "dont-want-to-update"
foo: |-
.
.
.
Необходимо обновить значение в поле a
с actual a
на updated a
Пытался обновить с помощью yq
и jq
yq 'select(.action == "want-to-update").foo' sample.yaml | jq '.a = "updated a" | tostring' | xargs -0 -n1 -I{} yq 'select(.action == "want-to-update").foo = {}' -i sample.yaml
Получение вывода, как показано ниже:
---
action: "want-to-update"
foo: |-
{"a":"updated a","b":"actual B","c":"actual C"}
---
.
.
Но я хочу более красивую версию выше:
---
action: "want-to-update"
foo: |-
{
"a" : "updated A",
"b" : "actual B",
"c" : "actual C"
}
---
В общем, удалить tostring
json=$(
yq 'select(.action == "want-to-update").foo' sample.yaml \
| jq '.a = "updated a"'
)
escaped_quotes=${json//\"/\\\"}
yq 'select(.action == "want-to-update").foo = "'"${escaped_quotes}"'"' sample.yaml
---
action: "want-to-update"
foo: |-
{
"a": "updated a",
"b": "actual B",
"c": "actual C"
}
---
action: "dont-want-to-update"
foo: |-
"ok"
Используя fromjson
и tojson
, вы можете декодировать и кодировать JSON на лету, поэтому все это можно сделать всего одним вызовом yq (без jq и подстановки команд не требуется):
yq -i 'select(.action == "want-to-update").foo |= (
fromjson | .a = "updated a" | tojson
)' sample.yaml
Примечание № 2: tojson
также принимает размер отступа в качестве параметра, поэтому, возможно, tojson(4)
будет лучше соответствовать исходному форматированию данных JSON.
Примечание. Чтобы получить это одноразовое решение с компактным форматированием данных JSON, замените
tojson
на@json
(а для эстетической симметрии такжеfromjson
на@jsond
).