Filtragem e seleção de JSON com pipelines do jq
Navegue por objetos e matrizes aninhados usando seletores, pipes e o filtro select do jq.
Filtragem e seleção de JSON com pipelines do jq é uma aula grátis de Linux Command Line & Bash Scripting Mastery no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Linux Command Line & Bash Scripting Mastery, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Linux Command Line & Bash Scripting Mastery inclui 4 aulas no total.
O que é jq e por que usá-lo?
jq é uma ferramenta de linha de comando leve e poderosa para analisar, filtrar e transformar dados JSON. Ele é o sed do JSON — você envia JSON para ele por um fluxo e recebe uma saída estruturada.
- Já vem instalado na maioria das distribuições Linux ou está disponível por meio de
apt install jq/brew install jq - Funciona perfeitamente em fluxos do shell com
curl,cate outras ferramentas - Oferece suporte a filtragem, mapeamento, redução e conversão de formato
A chamada básica é: jq '<filter>' file.json ou por fluxo, como em cat file.json | jq '<filter>'. O filtro . (ponto) é a identidade — ele formata de maneira legível todo o documento.
# Pretty-print a JSON file
jq '.' data.json
# Or pipe from curl
curl -s https://api.github.com/users/torvalds | jq '.'Selecionando campos de objetos com notação de ponto
Para acessar um campo em um objeto JSON, use a notação de ponto: .fieldName. Você pode encadear seletores para navegar por objetos aninhados.
.name— campo de nível superior.address.city— campo aninhado."field-with-dash"— campos com caracteres especiais precisam de aspas
Se o campo não existir, jq retornará null em vez de produzir um erro. Isso torna seu uso seguro em scripts, sem verificações adicionais de nulo para campos opcionais.
# Given: {"name":"Alice","address":{"city":"Berlin","zip":"10115"}}
echo '{"name":"Alice","address":{"city":"Berlin","zip":"10115"}}' | jq '.name'
# Output: "Alice"
echo '{"name":"Alice","address":{"city":"Berlin","zip":"10115"}}' | jq '.address.city'
# Output: "Berlin"Acessando elementos de matrizes e iterando
As matrizes JSON são acessadas com a notação de colchetes. jq usa índices começando em zero.
.items[0]— primeiro elemento.items[-1]— último elemento.items[1:3]— fatia (do índice 1 até, mas sem incluir, o 3).items[]— desmembrar a matriz: gera cada elemento como um valor separado (este é o iterador)
O iterador [] é fundamental para os fluxos do jq — ele permite aplicar filtros posteriores a cada elemento de maneira independente.
# Given an array of users
echo '[{"name":"Alice"},{"name":"Bob"},{"name":"Carol"}]' | jq '.[0]'
# Output: {"name":"Alice"}
# Iterate all elements and extract .name from each
echo '[{"name":"Alice"},{"name":"Bob"},{"name":"Carol"}]' | jq '.[].name'
# Output:
# "Alice"
# "Bob"
# "Carol"Criando fluxos jq com o operador de canalização
Assim como o canal do shell |, jq tem seu próprio operador interno de canalização. Ele passa a saída de um filtro como entrada para o próximo.
jq '.users[] | .name'— itera pelos usuários e depois extrai o nome de cada umjq '.data | .items[] | .id'— navega até os dados, desmembra os itens e extrai o identificador
Os canais dentro de uma expressão jq permitem criar transformações complexas passo a passo. Cada estágio recebe o que o estágio anterior produziu — inclusive vários valores vindos de um iterador.
Ideia principal: quando um iterador produz N valores, cada filtro posterior é executado N vezes, uma vez para cada valor.
# Nested pipeline: navigate -> iterate -> extract
echo '{"users":[{"name":"Alice","age":30},{"name":"Bob","age":25}]}' \
| jq '.users[] | .name'
# Output:
# "Alice"
# "Bob"
# Chain more stages
echo '{"users":[{"name":"Alice","age":30},{"name":"Bob","age":25}]}' \
| jq '.users[] | .age'
# Output:
# 30
# 25Filtrando com select()
O filtro select(condition) deixa um valor passar somente se a condição for verdadeira; caso contrário, não produz saída. Ele é o equivalente, no jq, a grep ou WHERE em SQL.
select(.age > 18)— mantém os objetos em que a idade é maior que 18select(.status == "active")— verifica a igualdadeselect(.name | startswith("A"))— teste de texto aninhado
Combine select com o iterador para filtrar matrizes: .items[] | select(.active) gera somente os elementos em que .active é verdadeiro.
# Filter array elements by a condition
echo '[{"name":"Alice","age":30},{"name":"Bob","age":17},{"name":"Carol","age":25}]' \
| jq '.[] | select(.age >= 18) | .name'
# Output:
# "Alice"
# "Carol"
# Filter by string equality
echo '[{"name":"Alice","role":"admin"},{"name":"Bob","role":"user"}]' \
| jq '.[] | select(.role == "admin") | .name'
# Output: "Alice"Reconstruindo objetos e matrizes com {} e []
jq permite remodelar dados construindo novos objetos com {} e novas matrizes com [].
{name: .name, city: .address.city}— seleciona e renomeia campos em um novo objeto[.items[] | .id]— reúne os valores iterados novamente em uma matriz- Forma abreviada:
{name, age}equivale a{name: .name, age: .age}
Envolver um fluxo em [...] é chamado de construção de matriz e é essencial quando você quer uma matriz JSON como saída, em vez de um fluxo de valores.
# Reshape: keep only selected fields
echo '[{"id":1,"name":"Alice","password":"secret"},{"id":2,"name":"Bob","password":"secret"}]' \
| jq '[.[] | {id, name}]'
# Output:
# [
# {"id": 1, "name": "Alice"},
# {"id": 2, "name": "Bob"}
# ]
# Collect filtered names into an array
echo '[{"name":"Alice","active":true},{"name":"Bob","active":false}]' \
| jq '[.[] | select(.active) | .name]'
# Output: ["Alice"]Trabalhando com matrizes aninhadas e descida recursiva
JSON do mundo real geralmente é profundamente aninhado. jq oferece duas ferramentas para navegação profunda:
.a.b.c— caminho explícito quando a estrutura é conhecida.. | .fieldName?— descida recursiva: percorre cada nó da árvore e gera os valores nos locais em que a chave existe
O operador ? (tentativa) suprime erros quando um campo não existe em determinado nó, o que é essencial ao usar descida recursiva em árvores heterogêneas.
Use a descida recursiva com moderação em documentos grandes — ela visita cada nó e pode ser lenta. Prefira caminhos explícitos quando a estrutura for previsível.
# Explicit deep path
echo '{"a":{"b":{"c":42}}}' | jq '.a.b.c'
# Output: 42
# Recursive descent: find all "id" values anywhere in the tree
echo '{"users":[{"id":1,"profile":{"id":99}},{"id":2}]}' \
| jq '.. | .id?'
# Output:
# 1
# 99
# 2Exemplo prático: analisando respostas de API com curl
Um dos casos de uso mais comuns do jq é analisar respostas de APIs REST obtidas com curl. Combinar curl -s (silencioso) com um fluxo jq fornece uma extração de dados limpa e adequada para scripts.
- Extrair um único valor:
curl -s URL | jq '.field' - Criar uma tabela-resumo: iterar por uma matriz e reconstruir objetos apenas com os campos necessários
- Usar
-r(saída bruta) para remover as aspas ao redor dos valores de texto — essencial ao atribuí-los a variáveis do shell
Dica: sempre adicione -r quando a saída do jq for usada como variável do shell ou canalizada para outro comando.
#!/usr/bin/env bash
# Fetch GitHub repo info and extract specific fields
REPO="torvalds/linux"
RESPONSE=$(curl -s "https://api.github.com/repos/${REPO}")
# Extract fields
STARS=$(echo "$RESPONSE" | jq -r '.stargazers_count')
LANG=$(echo "$RESPONSE" | jq -r '.language')
DESC=$(echo "$RESPONSE" | jq -r '.description')
echo "Stars : $STARS"
echo "Lang : $LANG"
echo "Desc : $DESC"Usando map() e map_values()
jq oferece duas funções convenientes de ordem superior para transformar coleções:
map(f)— aplica o filtrofa cada elemento de uma matriz, retornando uma nova matriz. Equivale a[.[] | f].map_values(f)— aplicafa cada valor de um objeto ou matriz, preservando as chaves/índices.
Essas funções são mais legíveis do que envolver manualmente os fluxos em [] e representam o estilo idiomático do jq para transformações que devem continuar sendo matrizes.
# map: extract a field from each element
echo '[{"name":"Alice","score":95},{"name":"Bob","score":80}]' \
| jq 'map(.name)'
# Output: ["Alice", "Bob"]
# map with select: filter + transform in one step
echo '[{"name":"Alice","score":95},{"name":"Bob","score":60}]' \
| jq 'map(select(.score >= 70) | .name)'
# Output: ["Alice"]
# map_values: multiply every value in an object by 2
echo '{"a":1,"b":2,"c":3}' | jq 'map_values(. * 2)'
# Output: {"a":2,"b":4,"c":6}Lidando com campos opcionais e valores padrão com //
Dados JSON de fontes externas geralmente são inconsistentes — campos podem estar ausentes ou nulos. jq oferece o operador alternativo // (barra dupla) para fornecer um valor padrão.
.nickname // "anonymous"— usa.nicknamese ele não for nulo/falso; caso contrário, usa"anonymous".count // 0— valor padrão numérico- Combine com
select:select((.status // "inactive") == "active")
Isso é muito mais conciso do que o equivalente no shell, ${VAR:-default}, e pode ser combinado facilmente dentro de fluxos mais longos.
# Provide defaults for missing/null fields
echo '[{"name":"Alice","role":"admin"},{"name":"Bob"}]' \
| jq '[.[] | {name, role: (.role // "user")}]'
# Output:
# [
# {"name": "Alice", "role": "admin"},
# {"name": "Bob", "role": "user"}
# ]
# Numeric default
echo '{"items":[1,2,3]}' | jq '.total // 0'
# Output: 0Script prático: analisador de registros JSON
O registro estruturado em JSON é padrão nos sistemas modernos. Veja um script realista que lê um arquivo de registro JSON delimitado por quebras de linha, filtra as entradas de erro e formata um resumo legível.
Principais padrões utilizados:
-c(saída compacta) — um objeto JSON por linha, útil para canalizar para laços do shell--arg name value— injeta uma variável do shell como argumento de texto do jqselectpara filtragem por nível de registro-rpara saída de texto bruto adequada paraecho
#!/usr/bin/env bash
# Parse newline-delimited JSON logs and report ERRORs
# Each log line: {"level":"ERROR","msg":"...","ts":"2024-01-15T10:23:00Z","svc":"auth"}
LOG_FILE="/var/log/app/app.log"
LEVEL="ERROR"
echo "=== $LEVEL entries in $LOG_FILE ==="
jq -r --arg lvl "$LEVEL" \
'select(.level == $lvl) | "[\(.ts)] [\(.svc)] \(.msg)"' \
"$LOG_FILE"
# Count errors per service
echo ""
echo "=== Error count by service ==="
jq -r --arg lvl "$LEVEL" \
'select(.level == $lvl) | .svc' "$LOG_FILE" \
| sort | uniq -c | sort -rnVerificação de conhecimento: comportamento de select() no jq
Teste sua compreensão de como select() funciona dentro de um fluxo do jq.
Considere o seguinte comando:
echo '[{"name":"Alice","age":30},{"name":"Bob","age":17},{"name":"Carol","age":22}]' | jq '[.[] | select(.age >= 18) | .name]'Qual será o resultado?
Recapitulação da lição: fluxos do jq para filtrar JSON
Você aprendeu os principais recursos do jq para navegar e filtrar JSON na linha de comando:
- Notação de ponto (
.field,.a.b.c) seleciona campos de objetos - Acesso a matrizes (
.[0],.[]) indexa e percorre matrizes - Operador de pipe (
|) encadeia filtros; cada etapa processa todos os valores da etapa anterior - select(cond) filtra valores, mantendo apenas aqueles em que a condição é verdadeira
- Construção de objetos/matrizes (
{},[],map()) reorganiza os dados em novas estruturas - Operador alternativo (
//) fornece valores padrão para campos nulos ou ausentes - Opção -r remove as aspas para atribuição a variáveis do shell; --arg injeta variáveis do shell com segurança
- Descida recursiva (
.. | .field?) pesquisa árvores profundamente aninhadas quando o caminho é desconhecido
Com esses blocos básicos, você pode transformar qualquer resposta de uma API JSON, arquivo de registro ou configuração exatamente nos dados de que seus scripts precisam — tudo sem sair do terminal.
Perguntas Frequentes
A aula “Filtragem e seleção de JSON com pipelines do jq” é grátis?
Sim — o texto completo de “Filtragem e seleção de JSON com pipelines do jq” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Linux Command Line & Bash Scripting Mastery, atualize para CoddyKit PRO. O curso de Linux Command Line & Bash Scripting Mastery inclui 4 aulas no total.
O que vou aprender em “Filtragem e seleção de JSON com pipelines do jq”?
Navegue por objetos e matrizes aninhados usando seletores, pipes e o filtro select do jq. Você pratica Linux Command Line & Bash Scripting Mastery com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Linux Command Line & Bash Scripting Mastery?
Nenhuma experiência prévia é necessária. Linux Command Line & Bash Scripting Mastery no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “Filtragem e seleção de JSON com pipelines do jq”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Linux Command Line & Bash Scripting Mastery?
Sim. Cada aula de Linux Command Line & Bash Scripting Mastery inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Filtragem e seleção de JSON com pipelines do jq
- Transformação e criação de objetos JSON com jq
- Consumo conjunto de APIs REST com curl e jq
- Edição de arquivos de configuração YAML com yq