Lee los datos de json en el script de shell

En shell tengo un requisito en el que tengo que leer la respuesta JSON que está en el siguiente formato:

{ "Messages": [ { "Body": "172.16.1.42|/home/480/1234/5-12-2013/1234.toSort", "ReceiptHandle": "uUk89DYFzt1VAHtMW2iz0VSiDcGHY+H6WtTgcTSgBiFbpFUg5lythf+wQdWluzCoBziie8BiS2GFQVoRjQQfOx3R5jUASxDz7SmoCI5bNPJkWqU8ola+OYBIYNuCP1fYweKl1BOFUF+o2g7xLSIEkrdvLDAhYvHzfPb4QNgOSuN1JGG1GcZehvW3Q/9jq3vjYVIFz3Ho7blCUuWYhGFrpsBn5HWoRYE5VF5Bxc/zO6dPT0n4wRAd3hUEqF3WWeTMlWyTJp1KoMyX7Z8IXH4hKURGjdBQ0PwlSDF2cBYkBUA=", "MD5OfBody": "53e90dc3fa8afa3452c671080569642e", "MessageId": "e93e9238-f9f8-4bf4-bf5b-9a0cae8a0ebc" } ] } 

Aquí solo me preocupa el valor de la propiedad “Cuerpo”. Hice algunos bashs fallidos como:

  jsawk -a 'return this.Body' 

o

  awk -vk="Body" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]} 

Pero eso no fue suficiente. Puede alguien ayudarme con esto?

Hay jq para analizar json en la línea de comando:

  jq '.Body' 

Visite esto para jq: https://stedolan.github.io/jq/

tl; dr

 $ cat /tmp/so.json | underscore select '.Messages .Body' ["172.16.1.42|/home/480/1234/5-12-2013/1234.toSort"] 

Herramientas de JavaScript CLI

Puede usar herramientas de JavaScript CLI como

  • underscore-cli :
  • json: select () : selectores tipo CSS para JSON.

Ejemplo

Seleccione todos los name secundarios de un addons :

 underscore select ".addons > .name" 

The underscore-cli proporciona otros ejemplos del mundo real , así como el json: select () doc .

Del mismo modo, usando Bash regexp. Deberá poder arrebatar cualquier par clave / valor.

 key="Body" re="\"($key)\": \"([^\"]*)\"" while read -rl; do if [[ $l =~ $re ]]; then name="${BASH_REMATCH[1]}" value="${BASH_REMATCH[2]}" echo "$name=$value" else echo "No match" fi done 

La expresión regular se puede sintonizar para que coincida con múltiples espacios / tabs o líneas nuevas. No funcionaría si el valor se ha incrustado " . Esta es una ilustración. Es mejor utilizar un analizador” industrial “:)

Aquí hay una forma cruda de hacerlo: Transformar JSON en variables bash para eval .

Esto solo funciona para:

  • JSON que no contiene matrices anidadas, y
  • JSON de fonts confiables (de lo contrario, puede confundir su script de shell, quizás incluso pueda dañar su sistema, se le advirtió )

Bueno, sí, usa PERL para hacer este trabajo, gracias a CPAN, pero es lo suficientemente pequeño como para incluirlo directamente en un script y, por lo tanto, es fácil y rápido depurarlo:

 json2bash() { perl -MJSON -0777 -n -E 'sub J { my ($p,$v) = @_; my $r = ref $v; if ($r eq "HASH") { J("${p}_$_", $v->{$_}) for keys %$v; } elsif ($r eq "ARRAY") { $n = 0; J("$p"."[".$n++."]", $_) foreach @$v; } else { $v =~ '"s/'/'\\\\''/g"'; $p =~ s/^([^[]*)\[([0-9]*)\](.+)$/$1$3\[$2\]/; $p =~ tr/-/_/; $p =~ tr/A-Za-z0-9_[]//cd; say "$p='\''$v'\'';"; } }; J("json", decode_json($_));' } 

eval "$(json2bash <<<'{"a":["b","c"]}')" como eval "$(json2bash <<<'{"a":["b","c"]}')"

No muy probado, sin embargo. Actualizaciones, advertencias y más ejemplos ver mi GIST .

Actualizar

(Desafortunadamente, la siguiente es una solución de solo enlace, ya que el código C es demasiado largo para duplicarlo aquí).

Para todos aquellos a quienes no les gusta la solución anterior, ahora hay un progtwig C json2sh que (con suerte) convierte JSON en variables de shell. A diferencia del fragmento perl , puede procesar cualquier JSON, siempre que esté bien formado.

Advertencias:

  • json2sh no fue probado mucho.
  • json2sh puede crear variables, que comienzan con el patrón shellshock () {

Escribí json2sh para poder post-procesar .bson con Shell:

 bson2json() { printf '['; { bsondump "$1"; echo "\"END$?\""; } | sed '/^{/s/$/,/'; echo ']'; }; bsons2json() { printf '{'; c=''; for a; do printf '%s"%q":' "$c" "$a"; c=','; bson2json "$a"; done; echo '}'; }; bsons2json */*.bson | json2sh | .. 

Explicado:

  • bson2json vuelca un archivo .bson tal que los registros se convierten en una matriz JSON
    • Si todo funciona bien, se aplica END0 -Marker, de lo contrario verá algo como END1 .
    • El END -Marker es necesario; de lo contrario, los archivos .bson vacíos no se mostrarán.
  • bsons2json vuelca un grupo de archivos .bson como un objeto, donde la salida de bson2json está indexada por el nombre del archivo.

Esto luego es json2sh por json2sh , de modo que puede usar grep / source / eval / etc. lo que necesita, para llevar los valores al caparazón.

De esta forma, puede procesar rápidamente el contenido de un volcado de MongoDB a nivel de caparazón, sin necesidad de importarlo primero a MongoDB.