2017-08-03 1 views
0

J'ai une exigence où je dois comparer les clés des deux chaînes en utilisant un script shell Unix. Je crée la chaîne json en utilisant la chaîne source, donc je dois m'assurer que toutes les clés de la chaîne source existent dans la chaîne JSON. c'est-à-dire que les clés 8, 35, 79, 80, 44, 33 et 10 doivent exister dans la chaîne Json. La chaîne json peut également être imbriquée.Comparer les clés dans une chaîne JSON en utilisant un script shell Unix

échantillon de chaîne source : 8=FIX|35=c|79=1|80=5|31=2|44=TEST|33=1.0|10=Test

échantillon JSON: {"8":"FIX", "35":"c", "79":[{"80":"5","31":"2"}], "33":"1.0", "44":"TEST", "10":"Test"}

Je vois beaucoup d'exemples avec JQ, mais je ne peux pas utiliser JQ maintenant. Quelqu'un peut-il m'aider s'il vous plaît sur cette question?

+1

Il est pas clair ce que vous demandez ici . Comment convertir la source en json, ou comment vérifier la conversion? Si vous avez déjà un code de conversion, postez le ici. Aussi quelle est la logique autour de la liste imbriquée pour '79'? – randomir

+0

Désolé si ce n'est pas clair pour vous .. Je cherchais le code pour vérifier le nombre de balises après la conversion, le nombre de balises présentes dans l'entrée devrait être le même que le nombre de balises présentes dans la sortie. Je ne devrais pas perdre de tags. – kattoor

+0

'jq' ou' ruby' ou 'python' ou' perl' ont des analyseurs json. Tout outil POSIX pur pouvant être contraint par la solution sera fragile. – dawg

Répondre

1

Si vous voulez obtenir le nombre de clés uniques dans chaque chaîne voici quelques idées (je suis sûr que cela peut facilement devenir l'analyse syntaxique enfer):

#!/bin/bash 
source_string="8=FIX|35=c|79=1|80=5|31=2|80=9|31=3|44=TEST|33=1.0|9=sample|10=Test" 
json_string="{8:FIX, 35:c, 79:[{80:5,31:2},{80:9}], 33:1.0, 44:TEST, 10:Test, 9:sample}" 

# get the count of uniq keys on source_string in file "source_key_count" 
grep -oP '[^\W]+(?==)' <<<"$source_string" | sort | uniq -c > source_key_count 

# get the count of uniq keys on json_string in file "json_key_count" 
grep -oP '(?<=[ ,{])[^\W]+(?=:)' <<<"$json_string" | sort | uniq -c > json_key_count 

echo "== join ==" 
# show tabular comparation of counts: key source json 
join -1 2 -2 2 source_key_count json_key_count | column -t 

echo "== diff ==" 
# show differences between both files 
diff source_key_count json_key_count 
+0

merci pour la mise à jour, cela fonctionne pour l'entrée fourni , mais n'a pas réussi à traiter s'il y a des balises qui se répètent comme suit: 'String1 =" 8 = FIX | 35 = c | 79 = 1 | 80 = 5 | 31 = 2 | 80 = 9 | 31 = 3 | 44 = TEST | 33 = 1.0 | 9 = échantillon | 10 = Test "' 'Chaîne2 =" {8: CORRECTIF, 35: c, 79: [{80: 5,31: 2}, {80 = 9}], 33 : 1.0, 44: TEST, 10: Test, 9: exemple} "' Dans la chaîne 2 le 31 est manquant .. :( – kattoor

+0

@kattoor Merci pour le feed back! Est-ce une faute de frappe sur string2: '{80 = 9}'? devrait-il être '{80: 9}'? – archemiro

+0

@kattoor Veuillez voir la mise à jour ... Je ne suis pas sûr de bien comprendre, vous voulez vérifier la clé-valeur ou la seule clé, car la clé 31 est en fait dans la chaîne2, ce qui n'est pas la valeur-clé 31 = 3 , mais pas non plus la valeur-clé 79 = 1. Dans votre question, vous avez dit les clés, c'est ce que les deux réponses initiales vous ont donné correctement ... cela devient un peu confus et vos données d'échantillon initial étaient des informations manquantes que vous demandez maintenant. – archemiro

1

Vous pouvez créer un tableau de clés pour chacune de vos deux entrées et les comparer avec des boucles imbriquées. Cela fonctionne pour vos échantillons:

#!/bin/bash 

EXIT_STATUS=0 

String1="8=FIX|35=c|79=1|80=5|31=2|44=TEST|33=1.0|10=Test" 

String2="{8:FIX, 35:c, 79:[{80:5,31:2}], 33:1.0, 44:TEST, 10:Test}" 

String1_keys=($(echo "$String1" | sed -e 's/=[^|]*|/ /g' -e 's/=.*//g')) 
String2_keys=($(echo "$String2" | sed -e 's/:\[/:nested, [/g' -e's/[{}\[\]]*//g' -e 's/:[^,]*,/ /g' -e 's/:.*$//g')) 

for key1 in ${String1_keys[*]}; do 
    keyFound=0 
    for key2 in ${String2_keys[*]}; do 
     if [ "$key1" == "$key2" ]; then 
      keyFound=1 
      break 
     fi 
    done 
    if [ $keyFound -eq 0 ]; then 
     echo "key $key1 does not exist in String2_keys" 2>&1 
     EXIT_STATUS=1 
    fi 
done 

if [ $EXIT_STATUS -eq 0 ]; then 
    echo "All keys in String1_keys exist in String2_keys" 
fi 

exit $EXIT_STATUS 

Selon le format de la chaîne que vous pompe, les déclarations sed sur les lignes 9 et 10 peuvent devoir être modifiés.

+0

merci pour la mise à jour, cela fonctionne pour l'entrée fournie, mais n'a pas réussi à traiter s'il y a des balises qui se répètent comme suit: 'String1 =" 8 = FIX | 35 = c | 79 = 1 | 80 = 5 | 31 = 2 | 80 = 9 | 31 = 3 | 44 = TEST | 33 = 1.0 | 9 = échantillon | 10 = Test "' 'Chaîne2 =" {8: CORRECTIF, 35: c, 79: [{80: 5,31 : 2}, {80 = 9}], 33: 1.0, 44: TEST, 10: Test, 9: sample} "' Dans la chaîne 2, le 31 est manquant .. :( – kattoor

+0

Merci pour le feed back! une faute de frappe sur string2: '{80 = 9}'? devrait-il être '{80: 9}'? – archemiro

+0

oui c'est une faute de frappe .. désolé .. :( – kattoor