J'essaie d'analyser un objet JSON dans un script Shell dans un tableau.
par exemple: [Amanda, 25, http://mywebsite.com]
Le JSON ressemble à:
{
"name" : "Amanda",
"age" : "25",
"websiteurl" : "http://mywebsite.com"
}
Je ne veux pas utiliser de bibliothèques, il serait préférable d'utiliser une expression régulière ou grep. J'ai fait:
myfile.json | grep name
Cela me donne "nom": "Amanda". Je pourrais le faire en boucle pour chaque ligne du fichier et l'ajouter à un tableau, mais je n'ai besoin que du côté droit et non de la ligne entière.
Si vous ne pouvez vraiment pas utiliser un analyseur JSON approprié tel que jq
[1] , essayez une solution basée sur awk
:
Bash 4.x:
readarray -t values < <(awk -F\" 'NF>=3 {print $4}' myfile.json)
Bash 3.x:
IFS=$'\n' read -d '' -ra values < <(awk -F\" 'NF>=3 {print $4}' myfile.json)
Cela stocke toutes les propriétés valeurs dans le tableau Bash ${values[@]}
, Que vous pouvez inspecter avecdeclare -p values
.
Ces solutions ont des limites:
Toutes ces limitations renforcent la recommandation d'utiliser un analyseur JSON approprié.
Remarque: Les solutions alternatives suivantes utilisent la commande Bash 4.x + readarray -t values
, Mais elles fonctionnent également avec l'alternative Bash 3.x, IFS=$'\n' read -d '' -ra values
.
grep
+ cut
combinaison : une seule commande grep
ne fonctionnera pas (sauf si vous utilisez [~ # ~] gnu [~ # ~]grep
- voir ci-dessous), mais l'ajout de cut
aide:
readarray -t values < <(grep '"' myfile.json | cut -d '"' -f4)
[~ # ~] gnu [~ # ~]grep
: Utilisation de -P
pour prendre en charge les PCRE, qui prennent en charge \K
pour supprimer tout ce qui a été trouvé jusqu'à présent (une alternative plus flexible à une assertion rétrospective) ainsi que les assertions prospectives ((?=...)
):
readarray -t values < <(grep -Po ':\s*"\K.+(?="\s*,?\s*$)' myfile.json)
Enfin, voici une solution pure Bash (3.x +) :
Ce qui en fait une alternative viable en termes de performances, c'est que aucun utilitaire externe n'est appelé dans chaque itération de boucle; cependant, pour les fichiers d'entrée plus volumineux, une solution basée sur des utilitaires externes sera beaucoup plus rapide.
#!/usr/bin/env bash
declare -a values # declare the array
# Read each line and use regex parsing (with Bash's `=~` operator)
# to extract the value.
while read -r line; do
# Extract the value from between the double quotes
# and add it to the array.
[[ $line =~ :[[:blank:]]+\"(.*)\" ]] && values+=( "${BASH_REMATCH[1]}" )
done < myfile.json
declare -p values # print the array
[1] Voici à quoi une solution robuste basée sur jq
ressemblerait (Bash 4.x):readarray -t values < <(jq -r '.[]' myfile.json)
jq est assez bon pour résoudre ce problème
paste -s <(jq '.files[].name' YourJsonString) <(jq '.files[].age' YourJsonString) <( jq '.files[].websiteurl' YourJsonString)
Pour que vous obteniez un tableau et que vous puissiez grep toutes les lignes ou awk imprimer toutes les colonnes que vous voulez
Vous pouvez utiliser une doublure sed one pour y parvenir:
array=( $(sed -n "/{/,/}/{s/[^:]*:[[:blank:]]*//p;}" json ) )
Résultat:
$ echo ${array[@]}
"Amanda" "25" "http://mywebsite.com"
Si vous n'avez pas besoin/ne voulez pas de guillemets, le sed suivant les supprimera:
array=( $(sed -n '/{/,/}/{s/[^:]*:[^"]*"\([^"]*\).*/\1/p;}' json) )
Résultat:
$ echo ${array[@]}
Amanda 25 http://mywebsite.com
Cela fonctionnera également si vous avez plusieurs entrées, comme
$ cat json
{
"name" : "Amanda"
"age" : "25"
"websiteurl" : "http://mywebsite.com"
}
{
"name" : "samantha"
"age" : "31"
"websiteurl" : "http://anotherwebsite.org"
}
$ echo ${array[@]}
Amanda 25 http://mywebsite.com samantha 31 http://anotherwebsite.org
MISE À JOUR:
Comme indiqué par mklement0 dans les commentaires, il peut y avoir un problème si le fichier contient des espaces incorporés, par exemple "name" : "Amanda lastname"
. Dans ce cas, Amanda
et lastname
seront tous deux lus dans des champs de tableau séparés chacun. Pour éviter cela, vous pouvez utiliser readarray
, par exemple,
readarray -t array < <(sed -n '/{/,/}/{s/[^:]*:[^"]*"\([^"]*\).*/\1/p;}' json2)
Cela permettra également de résoudre tous les problèmes de globalisation, également mentionnés dans les commentaires.