Categories: Tecnologia

Como analisar arquivos JSON na linha de comando do Linux com jq

Fatmawati Achmad Zaenuri / Shutterstock

JSON é um dos formatos mais populares para transferência de dados baseados em texto na web. Está em toda parte, e você com certeza vai encontrar. Mostraremos como lidar com isso na linha de comando do Linux usando o jqcomando.

JSON e jq

JSON significa JavaScript Object Notation . É um esquema que permite que os dados sejam codificados em arquivos de texto simples, de forma autodescritiva. Não há comentários em um arquivo JSON – o conteúdo deve ser autoexplicativo. Cada valor de dados tem uma string de texto chamada “nome” ou “chave”. Isso informa qual é o valor dos dados. Juntos, eles são conhecidos como pares nome: valor ou pares chave: valor. Dois pontos ( :) separam uma chave de seu valor.

Um “objeto” é uma coleção de pares chave: valor. Em um arquivo JSON, um objeto começa com uma chave aberta ( {) e termina com uma chave de fechamento ( }). JSON também oferece suporte a “matrizes”, que são listas ordenadas de valores. Uma matriz começa com um colchete de abertura ( [) e termina com um de fechamento ( ]).

A partir dessas definições simples, é claro, pode surgir uma complexidade arbitrária. Por exemplo, objetos podem ser aninhados em objetos. Os objetos podem conter arrays e os arrays também podem conter objetos. Todos os quais podem ter níveis abertos de aninhamento.

Na prática, porém, se o layout dos dados JSON for complicado, o design do layout dos dados provavelmente deve ser repensado. Claro, se você não está gerando os dados JSON, apenas tentando usá-los, você não tem voz no layout. Nesses casos, infelizmente, você apenas tem que lidar com isso.

A maioria das linguagens de programação tem bibliotecas ou módulos que permitem analisar dados JSON. Infelizmente, o shell Bash não tem essa funcionalidade .

A necessidade sendo a mãe da invenção, porém, jqnasceu a utilidade! Com jq, podemos  facilmente analisar JSON no shell Bash. E não importa se você tem que trabalhar com um JSON elegante e bem projetado ou com o material de que são feitos os pesadelos.

Como instalar o jq

Tivemos que instalar jq em todas as distribuições Linux que usamos para pesquisar este artigo.

Para instalar jqno Ubuntu, digite este comando:

sudo apt-get install jq

Para instalar jqno Fedora, digite este comando:

sudo dnf install jq

Para instalar jqno Manjaro, digite este comando:

sudo pacman -Sy jq

Como tornar JSON legível

JSON não se preocupa com o espaço em branco e o layout não o afeta. Desde que siga as regras da gramática JSON , os sistemas que processam JSON podem lê-lo e entendê-lo. Por causa disso, JSON é frequentemente transmitido como uma string simples e longa, sem nenhuma consideração de layout. Isso economiza um pouco de espaço porque tabulações, espaços e caracteres de nova linha não precisam ser incluídos no JSON. Claro, a desvantagem de tudo isso é quando um humano tenta ler.

Vamos retirar um objeto JSON curto do  site da  NASA que nos diz a posição da Estação Espacial Internacional . Usaremos curl, que pode baixar arquivos  para recuperar o objeto JSON para nós.

Não nos importamos com nenhuma das mensagens de status  curl geralmente geradas, então digitaremos o seguinte, usando a -sopção (silenciosa):

curl -s http://api.open-notify.org/iss-now.json

Agora, com um pouco de esforço, você pode ler isso. Você tem que escolher os valores dos dados, mas não é fácil ou conveniente. Vamos repetir isso, mas desta vez vamos canalizar jq.

jqusa filtros para analisar JSON, e o mais simples desses filtros é um ponto ( .), que significa “imprimir o objeto inteiro”. Por padrão, jq imprime bem a saída.

Juntamos tudo e digitamos o seguinte:

curl -s http://api.open-notify.org/iss-now.json | jq.

Isso é muito melhor! Agora, podemos ver exatamente o que está acontecendo.

Todo o objeto é envolvido por colchetes. Ele contém duas chaves: pares de nomes: messagee timestamp. Ele também contém um objeto chamado iss_position, que contém dois pares de chave: valor:  longitudee latitude.

Vamos tentar mais uma vez. Desta vez, digitaremos o seguinte e redirecionaremos a saída para um arquivo chamado “iss.json”:

curl -s http://api.open-notify.org/iss-now.json | jq. > iss.json
cat iss.json

Isso nos dá uma cópia bem definida do objeto JSON em nosso disco rígido.

Acessando valores de dados

Como vimos acima,  jqpode extrair valores de dados canalizados de JSON. Ele também pode funcionar com JSON armazenado em um arquivo. Vamos trabalhar com arquivos locais para que a linha de comando não fique entulhada de curlcomandos. Isso deve tornar um pouco mais fácil de seguir.

A maneira mais simples de extrair dados de um arquivo JSON é fornecer um nome de chave para obter seu valor de dados. Digite um ponto e o nome da chave sem espaço entre eles. Isso cria um filtro a partir do nome da chave. Também precisamos informar jqqual arquivo JSON usar.

Nós digitamos o seguinte para recuperar o messagevalor:

jq .message iss.json

jqimprime o texto do message valor na janela do terminal.

Se você tiver um nome de chave que inclua espaços ou pontuação, deverá colocar o filtro entre aspas. Geralmente, toma-se cuidado ao usar caracteres, números e sublinhados apenas para que os nomes de chave JSON não sejam problemáticos.

Primeiro, digitamos o seguinte para recuperar o timestampvalor:

jq .timestamp iss.json

O valor do carimbo de data / hora é recuperado e impresso na janela do terminal.

Mas como podemos acessar os valores dentro do  iss_positionobjeto? Podemos usar a notação de ponto JSON. Incluiremos o iss_positionnome do objeto no “caminho” para o valor da chave. Para fazer isso, o nome do objeto dentro da chave precederá o nome da própria chave.

Nós latitudedigitamos o seguinte, incluindo o nome da chave (observe que não há espaços entre “.iss_position” e “.latitude”):

jq .iss_position.latitude iss.json

Para extrair vários valores, você deve fazer o seguinte:

  • Liste os nomes das chaves na linha de comando.
  • Separe-os com vírgulas ( ,).
  • Coloque-os entre aspas ( ") ou apóstrofos ( ').

Com isso em mente, digitamos o seguinte:

jq ".iss_position.latitude, .timestamp" iss.json

Os dois valores são impressos na janela do terminal.

Trabalho com matrizes

Vamos pegar um objeto JSON diferente da NASA.

Desta vez, usaremos uma lista dos astronautas que estão no espaço agora :

curl -s http://api.open-notify.org/astros.json

Ok, funcionou, então vamos fazer de novo.

Vamos digitar o seguinte para jqencaminhá-lo e redirecioná-lo para um arquivo chamado “astro.json”:

curl -s http://api.open-notify.org/astros.json | jq. > astro.json

Agora vamos digitar o seguinte para verificar nosso arquivo:

menos astro.json

Conforme mostrado abaixo, agora vemos a lista de astronautas no espaço, bem como suas naves espaciais.

Este objeto JSON contém uma matriz chamada people. Sabemos que é uma matriz por causa do colchete de abertura ( [) (destacado na imagem acima). É uma matriz de objetos em que cada um contém duas chaves: pares de valores:   namee craft.

Como fizemos anteriormente, podemos usar a notação de ponto JSON para acessar os valores. Devemos também incluir os colchetes ( []) no nome do array.

Com tudo isso em mente, digitamos o seguinte:

jq ".people []. name" astro.json

Desta vez, todos os valores de nome são impressos na janela do terminal. O que pedimos jqpara fazer foi imprimir o valor do nome para cada objeto no array. Muito legal, hein?

Podemos recuperar o nome de um único objeto se colocarmos sua posição no array entre colchetes ( []) na linha de comando. A matriz usa indexação de deslocamento zero , o que significa que o objeto na primeira posição da matriz é zero.

Para acessar o último objeto na matriz, você pode usar -1; para obter o penúltimo objeto na matriz, você pode usar -2 e assim por diante.

Às vezes, o objeto JSON fornece o número de elementos no array, que é o caso deste. Junto com a matriz, ele contém um par chave: nome chamado numbercom um valor de seis.

O seguinte número de objetos está nesta matriz:

jq ".people [1] .name" astro.json
jq ".people [3] .name" astro.json
jq ".people [-1] .name" astro.json
jq ".people [-2] .name" astro.json

Você também pode fornecer um objeto inicial e final dentro da matriz. Isso é chamado de “fatiar” e pode ser um pouco confuso. Lembre-se de que a matriz usa um deslocamento zero.

Para recuperar os objetos da posição de índice dois, até (mas não incluindo) o objeto na posição de índice quatro, digitamos o seguinte comando:

jq ".people [2: 4]" astro.json

Isso imprime os objetos no índice de array dois (o terceiro objeto no array) e três (o quarto objeto no array). Ele interrompe o processamento no índice de matriz quatro, que é o quinto objeto da matriz.

A maneira de entender melhor isso é experimentar na linha de comando. Você logo verá como funciona.

Como usar tubos com filtros

Você pode canalizar a saída de um filtro para outro e não precisa aprender um novo símbolo. O mesmo que a linha de comando do Linux,  jqusa a barra vertical ( |) para representar um tubo.

Diremos  jqpara canalizar o peoplearray para o .namefiltro, que deve listar os nomes dos astronautas na janela do terminal.

Nós digitamos o seguinte:

jq ".people [] | .name" astro.json

Criação de matrizes e modificação de resultados

Podemos usar jqpara criar novos objetos, como arrays. Neste exemplo, vamos extrair três valores e criar uma nova matriz que contém esses valores. Observe que os [colchetes de abertura ( ) e de fechamento ( ]) também são o primeiro e o último caracteres na string de filtro.

Nós digitamos o seguinte:

jq "[.iss-position.latitude, iss_position.longitude, .timestamp]" iss.json

A saída é colocada entre colchetes e separada por vírgulas, tornando-a uma matriz formada corretamente.

Os valores numéricos também podem ser manipulados à medida que são recuperados. Vamos extrair do timestamparquivo de posição ISS e extraí-lo novamente e alterar o valor que é retornado.

Para fazer isso, digitamos o seguinte:

jq ".timestamp" iss.json
jq ".timestamp - 1570000000" iss.json

Isso é útil se você precisar adicionar ou remover um deslocamento padrão de uma matriz de valores.

Vamos digitar o seguinte para nos lembrar do que o iss.jsonarquivo contém:

jq. iss.json

Digamos que queremos nos livrar do messagepar chave: valor. Não tem nada a ver com a posição da Estação Espacial Internacional. É apenas uma bandeira que indica que o local foi recuperado com sucesso. Se for excedente aos requisitos, podemos dispensá-lo. (Você também pode simplesmente ignorá-lo.)

Podemos usar jqa função delete de,,  del()para deletar um par chave: valor. Para excluir o par chave: valor da mensagem, digitamos este comando:

jq "del (.message)" iss.json

Observe que isso não o exclui realmente do arquivo “iss.json”; apenas o remove da saída do comando. Se você precisar criar um novo arquivo sem o messagepar chave: valor nele, execute o comando e redirecione a saída para um novo arquivo.

Objetos JSON mais complicados

Vamos recuperar mais alguns dados da NASA. Desta vez, usaremos um objeto JSON que contém informações sobre locais de impacto de meteoros de todo o mundo. Este é um arquivo maior com uma estrutura JSON muito mais complicada do que aqueles com os quais lidamos anteriormente.

Primeiro, digitaremos o seguinte para redirecioná-lo para um arquivo chamado “strikes.json”:

curl -s https://data.nasa.gov/resource/y77d-th95.json | jq. > strikes.json

Para ver a aparência do JSON, digitamos o seguinte:

menos strikes.json

Conforme mostrado abaixo, o arquivo começa com um colchete de abertura ( [), então o objeto inteiro é um array. Os objetos na matriz são coleções de pares chave: valor e há um objeto aninhado chamado geolocation. O geolocationobjeto contém mais pares chave: valor e uma matriz chamada coordinates.

Vamos recuperar os nomes das colisões de meteoros do objeto na posição de índice 995 até o final da matriz.

Vamos digitar o seguinte para canalizar o JSON por meio de três filtros:

jq ". [995:] |. [] | .name" strikes.json

Os filtros funcionam das seguintes maneiras:

  • .[995:]: Isso diz jqpara processar os objetos do índice de matriz 995 até o final da matriz. Nenhum número após os dois pontos ( :) é o que indica  jqpara continuar até o final da matriz.
  • .[]: Este iterador de array diz jqpara processar cada objeto no array.
  • .name: Este filtro extrai o valor do nome.

Com uma pequena mudança, podemos extrair os últimos 10 objetos do array. Um “-10” instrui jq para iniciar o processamento de objetos 10 de volta a partir do final da matriz.

Nós digitamos o seguinte:

jq ". [- 10:] |. [] | .name" strikes.json

Assim como nos exemplos anteriores, podemos digitar o seguinte para selecionar um único objeto:

jq ". [650] .name" strikes.json

Também podemos aplicar o fatiamento às cordas. Para fazer isso, digitaremos o seguinte para solicitar os primeiros quatro caracteres do nome do objeto no índice de matriz 234:

jq ". [234] .name [0: 4]" strikes.json

Também podemos ver um objeto específico em sua totalidade. Para fazer isso, digitamos o seguinte e incluímos um índice de matriz sem nenhuma chave: filtros de valor:

jq ". [234]" strikes.json

Se quiser ver apenas os valores, você pode fazer a mesma coisa sem os nomes das chaves.

Para nosso exemplo, digitamos este comando:

jq ". [234] []" strikes.json

Para recuperar vários valores de cada objeto, nós os separamos com vírgulas no seguinte comando:

jq ". [450: 455] |. [] | .name, .mass" strikes.json

Se você deseja recuperar valores aninhados, você deve identificar os objetos que formam o “caminho” para eles.

Por exemplo, para fazer referência aos coordinatesvalores, temos que incluir a matriz abrangente, o geolocationobjeto aninhado e a coordinatesmatriz aninhada , conforme mostrado abaixo.

Para ver os coordinatesvalores do objeto na posição de índice 121 da matriz, digitamos o seguinte comando:

jq ". [121] .geolocation.coordinates []" strikes.json

A função comprimento

A jq lengthfunção fornece métricas diferentes de acordo com o que foi aplicado, como:

  • Strings : o comprimento da string em bytes.
  • Objetos : o número de pares chave: valor no objeto.
  • Matrizes : o número de elementos da matriz na matriz.

O comando a seguir retorna o comprimento do namevalor em 10 dos objetos na matriz JSON, começando na posição de índice 100:

jq ". [100: 110] |. []. nome | comprimento" strikes.json

Para ver quantos pares chave: valor estão no primeiro objeto da matriz, digitamos este comando:

jq ". [0] | comprimento" strikes.json

As teclas de função

Você pode usar a função keys para descobrir mais sobre o JSON com o qual precisa trabalhar. Ele pode dizer quais são os nomes das chaves e quantos objetos existem em uma matriz.

Para encontrar as chaves do peopleobjeto no arquivo “astro.json”, digitamos este comando:

jq ".people. [0] | keys" astro.json

Para ver quantos elementos estão na peoplematriz, digitamos este comando:

jq ".people | keys" astro.json

Isso mostra que há seis elementos da matriz de deslocamento zero, numerados de zero a cinco.

A função has ()

Você pode usar a has()função para interrogar o JSON e ver se um objeto tem um nome de chave específico. Observe que o nome da chave deve ser colocado entre aspas. Vamos envolver o comando de filtro entre aspas simples ( '), da seguinte maneira:

jq '. [] | has ("nametype") 'strikes.json

Cada objeto na matriz é verificado, conforme mostrado abaixo.

Se você quiser verificar um objeto específico, inclua sua posição de índice no filtro de matriz, da seguinte maneira:

jq '. [678] | has ("nametype") 'strikes.json

Não chegue perto do JSON sem ele

O jqutilitário é o exemplo perfeito de software profissional, poderoso e rápido que torna a vida no mundo Linux um prazer.

Esta foi apenas uma breve introdução às funções comuns deste comando – há muito mais do que isso. Certifique-se de verificar o manual jq abrangente  se quiser se aprofundar.

maisroot

Recent Posts

O novo aplicativo “PC Manager” da Microsoft se parece muito com o CCleaner

Muitos aplicativos de limpeza estão disponíveis para Windows ao longo dos anos, mas hoje em…

1 ano ago

Como reiniciar um PS4

Seu PlayStation 4 está congelado? Seus jogos favoritos continuam travando? Reiniciar seu PS4 pode resolver…

1 ano ago

Veja por que as reticências são tão assustadoras ao enviar mensagens de texto…

A popularidade das mensagens de texto significou aprender uma forma totalmente nova de comunicação. Você…

1 ano ago

O telescópio James Webb acaba de capturar os “Pilares da Criação”

A foto dos "Pilares da Criação" tirada pelo Telescópio Espacial Hubble é uma das fotos…

1 ano ago

Você poderá baixar o Proton Drive mais cedo do que pensa

O Proton Drive saiu de seu estágio beta há algumas semanas, mas o aplicativo real…

1 ano ago

Como aumentar o zoom no Photoshop

Para ver suas fotos mais de perto ou para uma edição precisa , você pode…

1 ano ago