As operações de atribuição do jq podem executar uma atualização em tantos locais ao mesmo tempo quanto você pode nomear e são feitos para esse tipo de situação. Você pode usar
jq '(.. | .name?) |= "XXXX"'
para encontre cada campo chamado "nome" em qualquer lugar e substitua o valor de cada um de uma vez por "XXXX", e imprima o objeto resultante.
Este é apenas o exemplo ..|.a?
da documentação de descendência recursiva combinada com < href="https://stedolan.github.io/jq/manual/#Update-assignment:%7C="> atualizar tarefa .
Ele usa o operador de descendente recursivo ..
para encontrar todos os valores na árvore Em seguida, extrai o campo "nome" de cada um deles com .name
, suprime os erros de valores não correspondentes com ?
e em seguida, atualiza o objeto em todos os lugares de uma vez com "XXXX" usando o operador de atribuição de atualização |=
e gera o novo objeto.
Isso funcionará independentemente da estrutura do arquivo e atualizará todos os campos de nomes em todos os lugares.
Como alternativa, se o arquivo sempre tiver essa estrutura e esses campos específicos de "nome" que você deseja alterar , não apenas qualquer nome antigo, você também poderá listá-los e atribuir a eles como um grupo também:
jq '(.name, .contact[].name, .group[].name) |= "XXXX"'
Isso faz a mesma atribuição para
- o campo "nome" do objeto de nível superior;
- o campo "nome" do objeto todo na matriz "contato"; e
- o campo "nome" de todos os objetos na matriz "grupo".
tudo de uma só vez. Isso é particularmente útil se o arquivo puder ter campos de nome outros em algum lugar não relacionado que você não queira alterar. Ele encontra apenas os três conjuntos de locais lá nomeados e atualiza todos eles simultaneamente.
Se o valor for apenas um literal como aqui, então atribuição simples com =
também funciona e economiza um caractere: (..|.name?)="XXXX"
- você também deseja isso se seu valor for calculado com base no objeto de nível superior inteiro. Se, em vez disso, você quiser calcular o novo nome com base no nome antigo, precisará usar |=
. Se não tenho certeza do que usar, |=
geralmente tem um comportamento ligeiramente melhor nos casos de canto.
Se você tiver várias substituições para fazer , você pode canalizá-las:
jq '(..|.name?) = "XXXX" | (..|.lname?) = "1234"'
atualizará os campos "nome" e "lname" em todos os lugares e exibirá todo o objeto atualizado uma vez.
Algumas outras abordagens que podem funcionar:
-
Você também pode ser muito explícito sobre o que está selecionando com
(..|objects|select(has("name"))).name |= "XXXX"'
que encontra tudo, depois apenas os objetos, apenas os objetos que possuem um "nome", o campo de nome nesses objetos e a mesma atualização de antes.
- Se você estiver executando a versão de desenvolvimento do jq (improvável), a
walk
function também pode fazer o trabalho: walk(.name?="XXXX")
. Todas as outras versões funcionarão na última versão lançada, 1.5.
-
Uma atualização múltipla alternativa pode ser
jq '(..|has("name")?) += {name: "XXXX", lname: "1234"}'
que encontra tudo com um nome e depois define "name" e "lname" em cada objeto usando atribuição-atualização aritmética *=
e o corção de comportamento que +
tem para objetos .