Como posso filtrar uma parte específica de uma resposta JSON no shell ash?

0

Estou usando o wget com -qO para uma URL de atualizador específica para o OpenELEC, que fornece a seguinte resposta JSON, semelhante à abaixo.

{"data":{"update":"OpenELEC-RPi2.arm-5.0.8.tar","folder":"releases","host":"","MD5":""}}

Eu só preciso do nome completo do arquivo de tar e nada mais.

Qual é a melhor maneira de filtrar todas as outras informações não necessárias?

    
por James White 28.04.2015 / 14:37

6 respostas

4

jq faria:

$ jq ".data.update" <<< '{"data":{"update":"OpenELEC-RPi2.arm-5.0.8.tar","folder":"releases","host":"","MD5":""}}'
"OpenELEC-RPi2.arm-5.0.8.tar"

ou com -r :

jq -r ".data.update" <<< '{"data":{"update":"OpenELEC-RPi2.arm-5.0.8.tar","folder":"releases","host":"","MD5":""}}'
OpenELEC-RPi2.arm-5.0.8.tar

para obter a string (raw) sem aspas.

    
por 28.04.2015 / 14:39
1

Usando sed , canalize a saída de wget para

sed -n 's/^.*{"update":"\([^"]*\)".*$//p'

Isso corresponde à parte {"update": da string retornada e, em seguida, extrai o conteúdo entre aspas duplas após a parte correspondente.

    
por 28.04.2015 / 14:43
1

Como FloHimself disse, você deve realmente usar um analisador JSON real. Existem muitos casos de borda que não são facilmente abrangidos por um processador de texto simples.

Com essa ressalva:

sed 's/.*"update":"\([^"]\+\)".*//'
    
por 28.04.2015 / 14:46
1

Eu teria que dizer - use perl. Eu não tenho 100% de certeza se isso está instalado no seu sistema operacional, mas há uma grande chance de que seja - é um componente de instalação base bastante comum.

#!/usr/bin/env perl

use strict;
use warnings;

use JSON;
print decode_json ( <DATA> ) -> {data} -> {update}; 

__DATA__
{"data":{"update":"OpenELEC-RPi2.arm-5.0.8.tar","folder":"releases","host":"","MD5":""}}

Este seria um 'one liner' por:

perl -MJSON -0ne 'print decode_json($_)->{data}->{update}' jsonfile

A vantagem de fazer isso dessa forma é que você está usando um analisador JSON, então ele funcionará se o arquivo json contiver:

{"data":{"update":"OpenELEC-RPi2.arm-5.0.8.tar","folder":"releases","host":"","MD5":""}}

ou

{
   "data" : {
      "host" : "",
      "MD5" : "",
      "update" : "OpenELEC-RPi2.arm-5.0.8.tar",
      "folder" : "releases"
   }
}

Ou outra reformatação perfeitamente válida do JSON. É por isso que o uso de um analisador é realmente a maneira ideal de fazer isso, porque o JSON oficialmente não se importa onde seus feeds de linha vão, e permite o aninhamento - e isso tende a tornar expressões regulares e análises baseadas em linhas frágeis.

    
por 28.04.2015 / 19:05
0

Usando grep com o PCRE:

grep -Po '(?<=:").*\.tar(?=")'

Teste:

$ foo='{"data":{"update":"OpenELEC-RPi2.arm-5.0.8.tar","folder":"releases","host":"","MD5":""}}'

$ grep -Po '(?<=:").*\.tar(?=")' <<<"$foo"
OpenELEC-RPi2.arm-5.0.8.tar
    
por 28.04.2015 / 14:47
0

Supondo que você armazene o JSON em um arquivo chamado jsonfile , então:

awk -F "update" '{print $2}' jsonfile | awk -F ":" '{print $2}' | awk -F "," '{ gsub(/"/,"" ); print $1}'

Irá dar como resultado OpenELEC-RPi2.arm-5.0.8.tar .

Lembre-se de que não é um analisador de JSON, portanto, isso funcionará se você tiver sempre a mesma estrutura do exemplo.

    
por 28.04.2015 / 15:13