jq é o processador de JSON em linha de comando que todo administrador Linux e engenheiro DevOps deveria ter em seu kit de ferramentas. Quando você está trabalhando com APIs REST, analisando saída do Kubernetes, processando estado do Terraform, ou extraindo dados de arquivos de log, jq permite fatiar, filtrar e transformar JSON diretamente do terminal — sem necessidade de script Python.

Este guia cobre tudo desde extração básica de campos até transformações avançadas, com exemplos do mundo real que você usará diariamente.

Pré-requisitos

  • Um sistema Linux (qualquer distribuição)
  • Familiaridade básica com pipes shell e ferramentas de linha de comando
  • Dados JSON para trabalhar (usaremos exemplos ao longo do guia)

Instalando jq

No Debian/Ubuntu:

sudo apt update && sudo apt install -y jq

No RHEL/Fedora/AlmaLinux:

sudo dnf install -y jq

No Alpine:

sudo apk add jq

No macOS:

brew install jq

Verificar:

jq --version

jq vs Outras Ferramentas de Processamento JSON

FerramentaMelhor ParaDesvantagens
jqTransformações CLI rápidas, pipes shellLógica complexa fica verbosa
Python jsonProcessamento em múltiplas etapas, lógica complexaRequer runtime Python, mais código
yqProcessamento YAML (sintaxe tipo jq)Instalação separada, específico para YAML
fxExploração interativa de JSONNão é scriptável
gronTornar JSON pesquisável com grepUnidirecional (apenas achatamento)

jq vence quando você precisa de transformações rápidas e scriptáveis em um pipeline com zero dependências além do binário.

jq Básico: Extraindo Dados

O Filtro de Identidade

A operação jq mais simples formata JSON de forma elegante:

echo '{"name":"nginx","version":"1.25.3","status":"running"}' | jq '.'
{
  "name": "nginx",
  "version": "1.25.3",
  "status": "running"
}

Extraindo Campos

Use notação de ponto para extrair valores específicos:

echo '{"name":"nginx","version":"1.25.3","status":"running"}' | jq '.name'
"nginx"

Para obter a string bruta sem aspas, adicione -r:

echo '{"name":"nginx","version":"1.25.3"}' | jq -r '.name'
nginx

A flag -r é essencial para scripting. Sem ela, jq produz strings codificadas em JSON (com aspas), o que quebra atribuições de variáveis e comparações em bash.

Objetos Aninhados

echo '{"server":{"host":"10.0.0.1","port":8080}}' | jq '.server.port'
8080

Acesso a Arrays

echo '["nginx","apache","caddy"]' | jq '.[0]'
"nginx"

Obter todos os elementos:

echo '["nginx","apache","caddy"]' | jq '.[]'
"nginx"
"apache"
"caddy"

Trabalhando com Respostas Reais de APIs

Aqui está um cenário realista: consultando uma API REST e extraindo o que você precisa.

# Obter informações de usuário do GitHub
curl -s https://api.github.com/users/torvalds | jq '{login, name, public_repos, followers}'
{
  "login": "torvalds",
  "name": "Linus Torvalds",
  "public_repos": 7,
  "followers": 223000
}

Extraindo de Arrays de Objetos

A maioria das APIs retorna arrays. Veja como trabalhar com eles:

# Simular uma resposta de API
cat << 'EOF' | jq '.servers[] | {name, status}'
{
  "servers": [
    {"name": "web-01", "status": "running", "cpu": 45},
    {"name": "web-02", "status": "stopped", "cpu": 0},
    {"name": "db-01", "status": "running", "cpu": 78}
  ]
}
EOF
{
  "name": "web-01",
  "status": "running"
}
{
  "name": "web-02",
  "status": "stopped"
}
{
  "name": "db-01",
  "status": "running"
}

Filtrando Dados JSON com jq

A Função select()

Filtre arrays para apenas elementos correspondentes:

cat << 'EOF' | jq '.servers[] | select(.status == "running")'
{
  "servers": [
    {"name": "web-01", "status": "running", "cpu": 45},
    {"name": "web-02", "status": "stopped", "cpu": 0},
    {"name": "db-01", "status": "running", "cpu": 78}
  ]
}
EOF
{
  "name": "web-01",
  "status": "running",
  "cpu": 45
}
{
  "name": "db-01",
  "status": "running",
  "cpu": 78
}

Comparações Numéricas

# Servidores com uso de CPU acima de 50%
cat servers.json | jq '.servers[] | select(.cpu > 50) | .name'

Combinando Condições

# Servidores em execução com CPU alta
cat servers.json | jq '.servers[] | select(.status == "running" and .cpu > 50)'

Correspondência de Strings

# Servidores cujo nome contém "web"
cat servers.json | jq '.servers[] | select(.name | contains("web"))'

Para correspondência com regex:

# Nomes que correspondem a um padrão
cat servers.json | jq '.servers[] | select(.name | test("web-[0-9]+"))'

Transformando JSON com jq

Construindo Novos Objetos

Construa novas estruturas JSON a partir de dados existentes:

cat << 'EOF' | jq '.servers[] | {hostname: .name, healthy: (.status == "running"), load: (.cpu / 100)}'
{
  "servers": [
    {"name": "web-01", "status": "running", "cpu": 45},
    {"name": "db-01", "status": "running", "cpu": 78}
  ]
}
EOF
{
  "hostname": "web-01",
  "healthy": true,
  "load": 0.45
}
{
  "hostname": "db-01",
  "healthy": true,
  "load": 0.78
}

map() para Transformações de Arrays

Transforme cada elemento em um array:

echo '[1,2,3,4,5]' | jq 'map(. * 2)'
[2, 4, 6, 8, 10]

Exemplo prático — extraia apenas os nomes em um array:

cat servers.json | jq '[.servers[].name]'
["web-01", "web-02", "db-01"]

Ordenação e Agrupamento

# Ordenar por CPU decrescente
cat servers.json | jq '.servers | sort_by(.cpu) | reverse'

# Agrupar por status
cat servers.json | jq '.servers | group_by(.status)'

Agregações

# Contar servidores
cat servers.json | jq '.servers | length'

# Média de CPU
cat servers.json | jq '.servers | map(.cpu) | add / length'

# CPU máximo
cat servers.json | jq '.servers | max_by(.cpu) | .name'

jq em Scripts Shell

Armazenando Resultados em Variáveis

#!/bin/bash
response=$(curl -s https://api.github.com/users/torvalds)

name=$(echo "$response" | jq -r '.name')
repos=$(echo "$response" | jq -r '.public_repos')

echo "User: $name has $repos public repos"

Atenção: Sempre coloque a variável entre aspas em echo "$response". Variáveis sem aspas perdem espaços em branco e quebram a análise de JSON.

Iterando sobre Arrays JSON

#!/bin/bash
# Processar cada servidor da API
curl -s https://api.example.com/servers | jq -r '.[] | .name' | while read -r server; do
    echo "Checking $server..."
    ping -c 1 -W 2 "$server" > /dev/null 2>&1 && echo "  UP" || echo "  DOWN"
done

Gerando Arquivos de Configuração a partir de JSON

# Converter inventário JSON em entradas /etc/hosts
cat inventory.json | jq -r '.hosts[] | "\(.ip)\t\(.hostname)"' >> /etc/hosts

Processamento Condicional

#!/bin/bash
status=$(curl -s https://api.example.com/health | jq -r '.status')

if [ "$status" != "healthy" ]; then
    echo "ALERT: Service is $status" | mail -s "Health Check Failed" admin@example.com
fi

Modificando JSON com jq

Atualizando Valores

echo '{"version": "1.0", "debug": false}' | jq '.version = "2.0" | .debug = true'
{
  "version": "2.0",
  "debug": true
}

Adicionando Campos

echo '{"name": "app"}' | jq '. + {"env": "production", "replicas": 3}'

Deletando Campos

echo '{"name":"app","secret":"abc123","version":"1.0"}' | jq 'del(.secret)'

Atualizando Valores Aninhados

echo '{"database":{"host":"old-host","port":5432}}' | jq '.database.host = "new-host"'

Receitas Práticas de jq do Mundo Real

Analisar Status de Pods do Kubernetes

kubectl get pods -o json | jq -r '.items[] | select(.status.phase != "Running") | "\(.metadata.name)\t\(.status.phase)"'

Extrair Valores de Output do Terraform

terraform output -json | jq -r 'to_entries[] | "\(.key) = \(.value.value)"'

Analisar Estatísticas de Containers Docker

docker inspect $(docker ps -q) | jq '.[] | {name: .Name, ip: .NetworkSettings.IPAddress, status: .State.Status}'

Processar Entradas de Log do CloudWatch

aws logs get-log-events --log-group-name /app/prod --log-stream-name main \
  | jq -r '.events[] | "\(.timestamp | . / 1000 | strftime("%Y-%m-%d %H:%M:%S")) \(.message)"'

Saída CSV a partir de JSON

cat servers.json | jq -r '.servers[] | [.name, .status, (.cpu | tostring)] | @csv'
"web-01","running","45"
"web-02","stopped","0"
"db-01","running","78"

Solução de Problemas

“parse error: Invalid numeric literal”: Sua entrada não é JSON válido. Valide primeiro com jq '.' file.json. Causa comum: a API retornou HTML (página de erro) em vez de JSON.

Saída “null” quando você espera dados: O nome do campo está errado ou não existe naquele caminho. Use jq 'keys' para ver os campos disponíveis, ou jq '.' | head -20 para inspecionar a estrutura.

Aspas em atribuições de variáveis: Sempre use jq -r (saída bruta) ao atribuir a variáveis shell. Sem ela, você obtém "value" em vez de value, o que quebra comparações de strings.

“Cannot iterate over null”: Você está tentando iterar (.[]) sobre um campo que é null ou está faltando. Adicione o operador opcional: .field[]? ou verifique com select(. != null).

Problemas de espaços em branco em pipes: Coloque suas variáveis entre aspas. echo $json | jq '.' quebra em espaços em branco. Use echo "$json" | jq '.' em vez disso.

Resumo

  • jq é a ferramenta padrão para processamento de JSON na linha de comando — um binário, sem dependências, funciona em qualquer lugar
  • Use .field, .[index] e .[] para extração básica; adicione -r para saída de string bruta em scripts
  • select() filtra arrays por condição — suporta correspondência de strings, comparações numéricas e regex com test()
  • Construa novas estruturas JSON com construção de objetos {key: .field} e map() para transformações de arrays
  • Combine com curl, kubectl, terraform e docker para automação do mundo real
  • sort_by(), group_by(), length, add lidam com ordenação e agregação
  • Modifique JSON com atribuição (.key = value), adição (. + {}), e deleção (del(.key))
  • Sempre use a flag -r e coloque variáveis entre aspas ao integrar jq em scripts bash

Bash Scripting for Sysadmins: The Essential Guide | Install Security Updates from the Command Line in Ubuntu