2
votes

Création JQ JSON

Nouveau dans la création JSON, a décidé d'essayer JQ depuis cette question . Cependant, lorsque j'ai essayé de l'implémenter, tout ce que j'ai reçu était la page d'aide pour JQ et ces types d'erreurs: ./test.sh: ligne 43: -: commande introuvable pour les trois dernières lignes .

#!/bin/bash

echo Starting

sensorType="XXX"
sensorLocation="XXX"
sensorCommand="XXXXX"

# Hardware information. 
systemTime=$(date +%d-%m-%Y_%H:%M:%S)
kernalName=$(uname -s)
nodeName=$(uname -i)
kernalRelease=$(uname -r)
kernalVersion=$(uname -v)
machine=$(uname -m)
processor=$(uname -p)
hardwarePlatform=$(uname -i)
operatingSystem=$(uname -o)
timeup=$(uptime)

# Software information.
softVersion=$(XXX version)

JSON_STRING=$( jq -n \
                -- arg systemTime "$systemTime" \
                -- arg sensorType "$sensorType" \
                -- arg sensorLocation "$sensorLocation" \
                -- arg sensorCommand "$sensorCommand" \
                -- arg kernalName "$kernalName" \
                -- arg nodeName "$nodeName" \
                -- arg kernalRelease "$kernalRelease" \
                -- arg kernalVersion "$kernalVersion" \ 
                -- arg machine "$machine" \ 
                -- arg processor "$processor"
                -- arg hardwarePlatform "$hardwarePlatform" \
                -- arg operatingSystem "$operatingSystem" \
                -- arg timeup "$timeup" \
                -- arg softVersion "$softVersion" \
                '{systemTime: $systemTime, sensorType: $sensorType, sensorLocation: $sensorLocation, kernalName: $kernalName, nodeName: $nodeName, kernalRelease: $kernalRelease, machine: $machine, processor: $processor, hardwarePlatform: $hardwarePlatform, operatingSystem: $operatingSystem, timeup: $timeup, softVersion: $softVersion }' )

echo $JSON_STRING

Je ne sais pas si c'est la manière la plus efficace d'utiliser JQ ou s'il existe une meilleure façon de l'implémenter. Mais j'aimerais savoir s'il existe un moyen plus efficace / plus simple d'accomplir cela.


3 commentaires

Cela semble être une faute de frappe dans votre commande jq . Il ne doit y avoir aucun espace entre le champ - et le champ arg


Merci @Inian!


Il vous manque également une barre oblique inverse sur la ligne processor , ce qui conduit à l'erreur «commande non trouvée»; le - pour hardwarePlatform est vu comme le début d'une nouvelle commande, pas comme un argument de la commande jq .


4 Réponses :


0
votes

Le premier problème, comme l'a souligné @Inian, est qu'il ne devrait pas y avoir d'espace entre "-" et "arg".

Le deuxième problème est qu'il ne devrait pas y avoir d'espace après la barre oblique inverse lorsqu'elle est utilisée (comme ici) pour la continuation de ligne: pour que la barre oblique inverse serve de caractère de continuation de ligne, elle doit échapper (c'est-à-dire immédiatement précéder) la nouvelle ligne.

Sinon, sauf peut-être pour certaines bizarreries telles que $ (Version XXX) , vous devriez être prêt à partir, ce qui ne veut pas dire qu'il n'y a pas de meilleures façons de créer l'objet JSON. Voir la section suivante pour une illustration d'une approche alternative.

Illustration d'une approche alternative

L'approche suivante peut être utilisée même si les clés et / ou valeurs contiennent des caractères de contrôle:

(
echo systemTime
date +%d-%m-%Y_%H:%M:%S
echo uname
uname -a
echo softVersion
echo XXX version
) | jq -nR '[inputs as $key | {($key): input}] | add'

Si l'on sait qu'aucune clé ou valeur ne contient de caractères de saut de ligne littéraux, la variante suivante, qui a le principal avantage de ne pas nécessiter l'option "-s", pourrait être utilisée :

FMT="%s\0%s\0"
(
printf $FMT systemTime $(date +%d-%m-%Y_%H:%M:%S)
printf $FMT newline "$(echo a; echo b)"
) | jq -sR '[split("\u0000") | range(0;length;2) as $i | {(.[$i]): .[$i + 1]}] | add'


1 commentaires

Je vous remercie! Le problème signalé par @Inian et la barre oblique inverse m'a attiré.



1
votes

Utilisez un tableau pour stocker les arguments avant d'appeler jq ; il est plus facile de répartir les arguments sur plusieurs lignes dans une affectation de tableau, car les barres obliques inverses ne sont pas nécessaires.

declare -A x
x=([systemTime]="$systemTime"
   [sensorType]="$sensorType"
   # etc
  )

declare -a jq_args
for k in "${!x[@]}"; do
  jq_args+=(--arg "$k" "${x[$k]}")
done

JSON_STRING=$( jq -n "${jq_args[@]}" ... )

Si vous utilisez une version de bash qui prend en charge tableaux associatifs, vous pouvez en outre construire simplement jq_args:

jq_args=(
   --arg systemTime "$systemTime"
   --arg sensorType "$sensorType"
   --arg sensorLocation "$sensorLocation"
   --arg sensorCommand "$sensorCommand"
   --arg kernalName "$kernalName"
   --arg nodeName "$nodeName"
   --arg kernalRelease "$kernalRelease"
   --arg kernalVersion "$kernalVersion" 
   --arg machine "$machine"
   --arg processor "$processor"
   --arg hardwarePlatform "$hardwarePlatform"
   --arg operatingSystem "$operatingSystem"
   --arg timeup "$timeup"
   --arg softVersion "$softVersion"
)
JSON_STRING=$( jq -n "${jq_args[@]}" '{
   systemTime: $systemTime,
   sensorType: $sensorType,
   sensorLocation: $sensorLocation,
   kernalName: $kernalName,
   nodeName: $nodeName,
   kernalRelease: $kernalRelease,
   machine: $machine,
   processor: $processor,
   hardwarePlatform: $hardwarePlatform,
   operatingSystem: $operatingSystem,
   timeup: $timeup,
   softVersion: $softVersion 
 }' )


2 commentaires

Petite astuce pour réduire un peu le filtre, {$ foo} revient à faire {foo: $ foo} . Vous pouvez donc l'utiliser sur toutes ces propriétés.


C'est drôle que vous le mentionniez; Je viens de me souvenir de cette fonctionnalité hier dans une autre réponse :)



0
votes

Je ne sais pas si c'est la manière la plus efficace d'utiliser JQ

Voici deux approches alternatives. Le premier est basé sur le format TSV et le second sur le format CSV.

Utilisation du format TSV

Ce qui suit suppose que ni les tabulations littérales ni les sauts de ligne littéraux n'apparaissent dans les clés ou les valeurs.

(
echo systemTime, $(date +%d-%m-%Y_%H:%M:%S)
echo uname, "$(uname -a)"
echo softVersion, XXX version
) | csv2json 
  | jq -n '[inputs as [$key, $value] | {($key): $value}] | add'

Utilisation d'un utilitaire CSV vers JSON

L'approche illustrée ici est probablement principalement intéressante si l'on commence par un fichier CSV de clé-valeur

Dans ce qui suit, nous utiliserons l'excellent utilitaire csv2json à https: // github.com/fadado/CSV Il y a en fait deux exécutables fournis ici. Les deux convertissent chaque ligne CSV en un tableau JSON. Nous utiliserons extended lié ​​symboliquement à csv2json.

FMT="%s\t%s\n"
(
printf $FMT systemTime $(date +%d-%m-%Y_%H:%M:%S)
printf $FMT uname "$(uname -a)"
printf $FMT softVersion "XXX version"
) | jq -nR '[inputs | split("\t") | {(.[0]): .[1]}] | add'

0 commentaires

0
votes

Si vous avez toutes les valeurs comme variables d'environnement, vous pouvez simplement utiliser l'objet env pour obtenir les valeurs. La syntaxe devient alors triviale.

systemTime=$(date +%d-%m-%Y_%H:%M:%S) \
kernalName=$(uname -s) \
nodeName=$(uname -i) \
kernalRelease=$(uname -r) \
kernalVersion=$(uname -v) \
machine=$(uname -m) \
processor=$(uname -p) \
hardwarePlatform=$(uname -i) \
operatingSystem=$(uname -o) \
timeup=$(uptime) \
jq -n 'env | {
    systemTime,
    sensorType,
    sensorLocation,
    kernalName,
    nodeName,
    kernalRelease,
    machine,
    processor,
    hardwarePlatform,
    operatingSystem,
    timeup,
    softVersion 
}'


0 commentaires