fazendo o loop através da matriz JSON no shell script

4

Abaixo está a saída do comando curl (informações do arquivo sobre a ramificação), necessidade de script ou comando para imprimir o nome do arquivo, tipo de arquivo e tamanho.

Eu tentei com jq mas consegui buscar um único valor (jq '.values []. size')

{
  "path": {
    "components": [],
    "name": "",
    "toString": ""
  },
  "revision": "master",
  "children": {
    "size": 5,
    "limit": 500,
    "isLastPage": true,
    "values": [
      {
        "path": {
          "components": [
            ".gitignore"
          ],
          "parent": "",
          "name": ".gitignore",
          "extension": "gitignore",
          "toString": ".gitignore"
        },
        "contentId": "c9e472ef4e603480cdd85012b01bd5f4eddc86c6",
        "type": "FILE",
        "size": 224
      },
      {
        "path": {
          "components": [
            "Jenkinsfile"
          ],
          "parent": "",
          "name": "Jenkinsfile",
          "toString": "Jenkinsfile"
        },
        "contentId": "e878a88eed6b19b2eb0852c39bfd290151b865a4",
        "type": "FILE",
        "size": 1396
      },
      {
        "path": {
          "components": [
            "README.md"
          ],
          "parent": "",
          "name": "README.md",
          "extension": "md",
          "toString": "README.md"
        },
        "contentId": "05782ad495bfe11e00a77c30ea3ce17c7fa39606",
        "type": "FILE",
        "size": 237
      },
      {
        "path": {
          "components": [
            "pom.xml"
          ],
          "parent": "",
          "name": "pom.xml",
          "extension": "xml",
          "toString": "pom.xml"
        },
        "contentId": "9cd4887f8fc8c2ecc69ca08508b0f5d7b019dafd",
        "type": "FILE",
        "size": 2548
      },
      {
        "path": {
          "components": [
            "src"
          ],
          "parent": "",
          "name": "src",
          "toString": "src"
        },
        "node": "395c71003030308d1e4148b7786e9f331c269bdf",
        "type": "DIRECTORY"
      }
    ],
    "start": 0
  }
}

O resultado esperado deve ser algo como abaixo

.gitignore    FILE     224

Jenkinsfile   FILE     1396

Obrigado antecipadamente :)

    
por Sugatur Deekshith S N 23.10.2018 / 11:08

4 respostas

3

Para o caso de uso fornecido na pergunta, a resposta do @JigglyNaga provavelmente é melhor do que isso, mas para alguma tarefa mais complicada, você também pode percorrer os itens da lista usando keys :

de file :

for k in $(jq '.children.values | keys | .[]' file); do
    ...
done

ou da string:

for k in $(jq '.children.values | keys | .[]' <<< "$MYJSONSTRING"); do
    ...
done

Então, por exemplo você pode usar:

for k in $(jq '.children.values | keys | .[]' file); do
    value=$(jq -r ".children.values[$k]" file);
    name=$(jq -r '.path.name' <<< "$value");
    type=$(jq -r '.type' <<< "$value");
    size=$(jq -r '.size' <<< "$value");
    printf '%s\t%s\t%s\n' "$name" "$type" "$size";
done | column -t -s$'\t'

se você não tem novas linhas para os valores, pode fazê-lo com uma única chamada jq dentro do loop, o que o torna muito mais rápido:

for k in $(jq '.children.values | keys | .[]' file); do
    IFS=$'\n' read -r -d '' name type size \
        <<< "$(jq -r ".children.values[$k] | .path.name,.type,.size" file)"
    printf '%s\t%s\t%s\n' "$name" "$type" "$size";
done | column -t -s$'\t'
    
por 23.10.2018 / 11:39
7

Extraindo os membros

jq -c '.children.values[]|[.path.components[0],.type,.size]'
  • .children.values[] produz todos os membros da matriz .values .
  • | canaliza o resultado anterior através do próximo filtro, mais ou menos como um pipe de shell
  • [ ... , ... , ... ] faz todos os termos aparecerem em uma única matriz
  • A opção -c produz o formato "compacto", ou seja, um objeto por linha

Resultado:

[".gitignore","FILE",224]
["Jenkinsfile","FILE",1396]
["README.md","FILE",237]
...

Formatando o resultado

Se você quiser produzir uma tabela perfeitamente alinhada, essa é uma tarefa que será mais bem tratada por outras ferramentas, como column ou paste .

jq -c '.children.values[]|[.path.components[0],.type,.size]' | column -t -s'[],"'
  • -t informa column para adivinhar o número de colunas com base na entrada
  • -s... especifica o (s) caractere (s) delimitador (es)

Resultado:

.gitignore   FILE       224
Jenkinsfile  FILE       1396
README.md    FILE       237

Isso depende dos caracteres [ , ] , , e " não aparecerem nos seus nomes de arquivos, o que não é uma suposição segura.

paste também pode organizar várias entradas lado a lado. Para isso, podemos remover completamente as estruturas JSON e exibir as linhas brutas (hat-tip para @muru):

jq -r '.children.values[]|.path.components[0],.type,.size' | paste - - -

paste - - - significa 3 colunas, todas lidas da mesma fonte. Desta vez, a única suposição é que os nomes de arquivos não contêm novas linhas.

    
por 23.10.2018 / 11:25
2

jq pode renderizar sua saída em vários formatos: consulte link

Para saída separada por tabulação:

$ jq -r '.children.values[] | [.path.name, .type, .size] | @tsv' file.json
.gitignore  FILE    224
Jenkinsfile FILE    1396
README.md   FILE    237
pom.xml FILE    2548
src DIRECTORY   
    
por 23.10.2018 / 18:37
1

Solução com ramda-cli :

% curl ... | ramda -o tsv '.children.values' 'map flat' 'map props ["path.name", "type", "size"]'
.gitignore      FILE    224
Jenkinsfile     FILE    1396
README.md       FILE    237
pom.xml FILE    2548
src     DIRECTORY

Primeiro, percorremos a lista de valores e, em seguida, mapeamos pela lista com flat para converter cada entrada que é uma estrutura de objeto profundo em uma estrutura superficial, com chaves separadas por pontos.

Em seguida, podemos mapear novamente a lista e escolher as propriedades desejadas com base em seus caminhos, representadas por strings.

Por fim, -o tsv cuida de converter a lista de listas resultante em formato tsv.

Para depurar ou entender melhor o que está acontecendo, você pode verificar o que cada argumento faz, removendo-os um por um do final do comando e observando a diferença na saída em cada etapa. São simplesmente operações (ou funções) aplicadas nos dados, um de cada vez, da esquerda para a direita.

    
por 23.10.2018 / 17:34