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
| Ferramenta | Melhor Para | Desvantagens |
|---|---|---|
| jq | Transformações CLI rápidas, pipes shell | Lógica complexa fica verbosa |
| Python json | Processamento em múltiplas etapas, lógica complexa | Requer runtime Python, mais código |
| yq | Processamento YAML (sintaxe tipo jq) | Instalação separada, específico para YAML |
| fx | Exploração interativa de JSON | Não é scriptável |
| gron | Tornar JSON pesquisável com grep | Unidirecional (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-rpara saída de string bruta em scripts select()filtra arrays por condição — suporta correspondência de strings, comparações numéricas e regex comtest()- Construa novas estruturas JSON com construção de objetos
{key: .field}emap()para transformações de arrays - Combine com
curl,kubectl,terraformedockerpara automação do mundo real sort_by(),group_by(),length,addlidam com ordenação e agregação- Modifique JSON com atribuição (
.key = value), adição (. + {}), e deleção (del(.key)) - Sempre use a flag
-re 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