Créer JSON à l'aide de jq de canalisations séparées des clés et des valeurs dans bash
Je suis en train de créer un objet json à partir d'une chaîne en bash. La chaîne est comme suit.
CONTAINER|CPU%|MEMUSAGE/LIMIT|MEM%|NETI/O|BLOCKI/O|PIDS
nginx_container|0.02%|25.09MiB/15.26GiB|0.16%|0B/0B|22.09MB/4.096kB|0
La sortie est de docker stats de commande et mon objectif final est de publier des statistiques personnalisées à aws cloudwatch. Je voudrais format de cette chaîne json.
{
"CONTAINER":"nginx_container",
"CPU%":"0.02%",
....
}
J'ai utilisé jq commande avant et il semble que cela devrait bien fonctionner dans ce cas mais je n'ai pas été en mesure de trouver une bonne solution pour le moment. Autres que de coder en dur les noms de variables et de l'indexation à l'aide de sed ou awk. Ensuite, la création d'un json à partir de zéro. Toutes les suggestions seraient appréciées. Merci.
Je ne pense pas que JQ est l'outil pour le travail (c'est du JSON/JSON) j'ai fait quelque chose de similaire récemment et s'est terminé vers le haut en utilisant le RUBIS et CSV JSON modules (CSV pouvez utiliser | comme séparateur) Python a les mêmes classes
hein??? jq est absolument un excellent outil pour ce travail.
jq n'est pas limité à du JSON. Il peut lire les premières chaînes (voir la
limité à JSON, soit, pour que la matière; la version actuelle de plus prend en charge l'écriture de CSV, %-codé Uri, HTML, POSIX-sh-compatible coque-échappé à la syntaxe, et encodée en base64, les chaînes littérales.
être juste, j'ai raté le CSV d'entrée spec plus tôt. Alors que
hein??? jq est absolument un excellent outil pour ce travail.
jq n'est pas limité à du JSON. Il peut lire les premières chaînes (voir la
-R
option), et a regex de soutien (de sorte qu'il peut analyser la syntaxe que vous voyez l'ajustement de l'envoyer).limité à JSON, soit, pour que la matière; la version actuelle de plus prend en charge l'écriture de CSV, %-codé Uri, HTML, POSIX-sh-compatible coque-échappé à la syntaxe, et encodée en base64, les chaînes littérales.
être juste, j'ai raté le CSV d'entrée spec plus tôt. Alors que
jq
prend en charge native de sortie CSV, car elle n'a pas d'analyse du soutien qui s'étend sur les bizarreries de la langue (regexes être un piètre outil pour traiter les citations et d'échapper à la sémantique et l'aime), j'ai fini par utiliser une langue avec un natif CSV-l'analyse de la bibliothèque dans ce cas, moi aussi.
OriginalL'auteur michael_65 | 2016-08-09
Vous devez vous connecter pour publier un commentaire.
Préalable
Pour l'ensemble de la ci-dessous, il est supposé que votre contenu est dans une variable d'environnement nommée
s
:Ce moderne (jq)
Comment moderne (jq)
Cela nécessite de très nouveau (probablement de 1,5?)
jq
de travail, et un épais morceau de code. Pour le décomposer:-n
empêchejq
à partir de la lecture de l'entrée standard stdin sur son propre, en laissant l'intégralité des flux d'entrée disponibles pour être lu parinput
etinputs
- le premier pour lire une seule ligne, et le dernier à lire toutes les lignes restantes. (-R
, pour les matières premières d'entrée, les causes textuelle des lignes plutôt que des objets JSON pour être lu).[$keys, $vals] | transpose[]
, nous générons de[key, value]
paires (en Python termes, la compression de deux listes).{key:.[0],value:.[1]}
, nous faisons chaque[key, value]
paire dans un objet de la forme{"key": key, "value": value}
from_entries
, nous combinons ces paires d'objets contenant les clés et les valeurs.Ce (shell assistée)
Cela fonctionne avec un beaucoup plus âgés
jq
que ci-dessus, et est facilement approche qui a été retenue pour les cas où un natifjq
solution peut être plus difficile de se quereller:Comment (shell assistée)
La invoquée
jq
commande à partir de ci-dessus est similaire à:...en passant chaque clé et de la valeur de la bande (telle qu'elle est traitée comme une chaîne littérale plutôt que analysée comme JSON), puis se référant à eux individuellement.
Résultat
Les émettent:
Pourquoi
En bref: Car il est garanti que pour générer du JSON valide en tant que sortie.
Considèrent comme un exemple de pause plus naïf approches:
Sûr, ce sont des scénarios inattendus, mais
jq
sait comment traiter avec eux:...alors qu'une mise en œuvre qui ne comprennent pas de chaînes JSON pourrait facilement se retrouver émettant:
transpose
puisque vous avez déjà des tableaux de clés et de valeurs. La transposition efficacement zips ensemble qui vous permettra de créer de l'objet plutôt facilement.J'ai l'impression que je suis absent quelque chose qui devrait être évident-est-il un idiome qui fait plus de sens que
[$keys, $vals] | transpose | [ .[] | {"key": .[0], "value": .[1]} ] | from_entries
?Je ne sais pas si il y a un idiomatiques façon de le faire, mais je vois un certain nombre de façons, il pourrait être atteint. Personnellement, j'aime utiliser
from_entries
:[[$keys,$values] | transpose[] | {key:.[0],value:.[1]}] | from_entries
. Ou la création d'objets de paires et d'ajouter:[[$keys,$values] | transpose[] | {(.[0]):.[1]}] | add
. Ou à l'aide dereduce
pour affecter les valeurs:reduce ([$keys,$values] | transpose[]) as $p ({}; .[$p[0]] = $p[1])
Oooh -- que l'utilisation de la
add
est un truc que je n'avais pas été au courant. Brillant! 🙂Cela semble fonctionner:
jq -Rn '(input|split("|")) as $keys | (inputs | split("|")) as $vals | [[$keys, $vals] | transpose [] ...
. Je ne vois pas un moyen d'éviter les variables au total encore, probablement en raison de l'ordre dans lequel les filtres sont évalués.OriginalL'auteur Charles Duffy
Retourne:
Je serais séparée de la lecture de l'en-tête de la boucle de sorte que vous pouvez éviter la
LOOPNUM
logique:... | { IFS=: read -a jsonnames; while IFS=: read ...; do echo ...; done; }
.BTW, tuyauterie dans une boucle signifie que vous ne pouvez pas conserver l'état passé de la boucle de sortie [absente un tout nouveau bash avec la
lastpipe
option, ou une coquille où c'est le comportement par défaut commeksh
]. Voir BashFAQ #24 (mywiki.wooledge.org/BashFAQ/024) --while ...; done <newfile
, ou{ read header; while ...; done; } <newfile
, par opposition àcat newfile | while ...; done
, permettra d'éviter cette limitation.et chepner. Les gars, vous êtes terriblement bon à Bash.
OriginalL'auteur Nick Bull
Voici une solution qui utilise le
-R
et-s
options, ainsi quetransposer
:OriginalL'auteur jq170727
json_template='{"CONTAINER":"%s","CPU%":"%s","MEMUSAGE/LIMIT":"%s", "MEM%":"%s","NETI/O":"%s","BLOCKI/O":"%s","PIDS":"%s"}'
json_string=$(printf "$json_template" "nginx_container" "0.02%" "25.09MiB/15.26GiB" "0.16%" "0B/0B" "22.09MB/4.096kB" "0")
echo "$json_string"
Pas à l'aide de jq, mais possible d'utiliser des arguments et de l'environnement dans les valeurs.
CONTAINER=nginx_container
json_template='{"CONTAINER":"%s","CPU%":"%s","MEMUSAGE/LIMIT":"%s", "MEM%":"%s","NETI/O":"%s","BLOCKI/O":"%s","PIDS":"%s"}'
json_string=$(printf "$json_template" "$CONTAINER" "$1" "25.09MiB/15.26GiB" "0.16%" "0B/0B" "22.09MB/4.096kB" "0")
echo "$json_string"
OriginalL'auteur NoamG
Si vous êtes débutant avec les données tabulaires, je pense qu'il est plus logique d'utiliser quelque chose qui fonctionne avec des données tabulaires en natif, comme sqawk à faire en json, et ensuite utiliser jq travailler avec elle.
Sans
jq
,sqawk
donne un peu trop:OriginalL'auteur MatrixManAtYrService
Vous pouvez demander à docker pour vous donner des données JSON en premier lieu
Pour en savoir plus, voir: https://docs.docker.com/config/formatting/
OriginalL'auteur MatrixManAtYrService