Analyser une chaîne dans le script bash

Jai passé en revue dautres réponses mais je nai pas pu obtenir une explication appropriée sur la façon de procéder.

I avoir une variable de chaîne appelée id telle que id="{"name":"john"}". Comment puis-je obtenir 2 variables de cette chaîne comme-

key="name" value="john" 

Une explication détaillée serait appréciée car je veux comprendre lanalyse des chaînes dans bash.

Jusquà présent, jai « supprimé les accolades {} à partir de la chaîne-

id="$( echo "${id}" | tr -d {} )" 

Je ne peux » t inclure " là-dedans comme il renvoie une erreur. Recherche également quelque chose comme id.split(":") à la fin pour obtenir un tableau.

Commentaires

  • Pouvons-nous vous avertir de cette tactique / piste avant quil ne soit ‘ trop tard? Il semble que vous ayez json ou dautres données structurées. Peut-être quun outil dédié serait un moyen plus sûr de vous amener là où vous vous y allez?
  • Jai vu que jq est utilisé par dautres, mais je ne peux pas analyser cela sans un tiers
  • Importez-vous ces données à partir dun fichier? Peut-il y avoir plus dune paire de clés / valeurs? À quoi ressemblerait un guillemet double dans le cadre de la valeur?
  • @kev: Techniquement awk, sed et grep sont également des outils tiers. Si vous utilisez des données json, il ny a absolument aucune raison de ne pas disposer des outils appropriés pour les utiliser.
  • Ces données sont le résultat dune commande que je exécuté dans mon script. Il sera toujours dans ce format – 1 clé et 1 valeur.

Réponse

En utilisant jq:

id="{"name":"john"}" key=$(jq -r keys[] <<<"$id") value=$(jq -r .[] <<<"$id") 

-r: Avec cette option, si le filtre « s result est une chaîne, elle sera écrite directement sur la sortie standard plutôt que dêtre formatée comme une chaîne JSON avec des guillemets.

keys: Les touches de fonction intégrées, donné un objet, renvoie ses clés dans un tableau.


Utilisation de json:

id="{"name":"john"}" key=$(json -ak <<<"$id") value=$(json -a "$key" <<<"$id") 

-a traite lentrée sous forme de tableau

-k renvoie les valeurs clés

Commentaires

  • merci pour lexplication. Fonctionne très bien. Je pense que ‘ est impossible danalyser une chaîne sans jq dans les scripts bash.
  • @kev: Il existe de nombreuses façons danalyser des chaînes mais ‘ est plutôt injuste pour appeler cela une chaîne et non des données JSON.
  • @kev Les données JSON peuvent être encodées. Pour lanalyser, vous devrez potentiellement le décoder. De plus, JSON ne se soucie pas des espaces (retours à la ligne, etc.) entre les clés et les valeurs, vous devrez donc en tenir compte. Cela a déjà été fait pour vous par les auteurs de lanalyseur JSON sous-jacent dans jq.

Réponse

Vous avez littéralement demandé à understand string parsing in bash donc jécrirai une réponse dans cet esprit, même si cest le mauvaise solution pour votre problème . Vous pouvez utiliser bash lui-même pour faire ce que vous voulez, si vous avez vraiment propre données sans caractères spéciaux, où spécial est défini comme tout ce qui se trouve en dehors de [A-Za-z0-9 ]:

$name":"john"}" $ # remove everything through the first "{" $ echo $id "name":"john"} $ # remove everything starting with the last "}" $ echo $id "name":"john" $ name="${id%:*}" # take everything before the ":" $ name="${name//\"/}" # remove quotes $ echo $name name $ value="${id#*:}" # take everything after the ":" $ value="${value//\"/}" # remove quotes $ echo $value john 

Tout cela est décrit dans « Expansion des paramètres » du manuel bash . Par exemple, ${parameter#word} qui Remove matching prefix pattern supprimera le texte word du début de $parameter. De même, % supprime le suffixe. // remplace toutes les occurrences dune chaîne par ce qui suit (dans lexemple ${foo//\"/} ci-dessus, des guillemets (qui doivent être échappés, donc apparaissent comme \") sont remplacés par la chaîne vide). Cependant, vous devez effectuer chaque substitution par elle-même: vous ne pouvez pas supprimer le début et de la fin de la chaîne avec une seule commande.

Vous avez probablement également remarqué que vous doivent échapper les caractères spéciaux, comme }, { et ". Tant que vous vous souvenez de bien faire les choses, vous pouvez écrire du code comme celui-ci assez facilement mais, aussi simple soit-il, il a tendance à être du code en écriture seule. Quand vous revenez à ceci code dans un an ou deux pour le réutiliser, vous allez regarder quelque chose comme #*\{} et penser à vous-même, WTF est-ce que cela veut dire? et puis copiez-le aveuglément dans un nouveau projet et votre code se cassera de manière subtile car il rencontre des caractères spéciaux auxquels vous ne vous attendiez pas.

Les exemples ci-dessus ne fonctionneront pas si vos paires nom-valeur contiennent des caractères spéciaux, comme des accolades, des guillemets ou des deux-points ou probablement dautres caractères. Donc, cela fonctionnera bien pour un grattage rapide et sale ou le cas dutilisation à 80%, mais vous ne devriez vraiment pas lutiliser en production ou à tout moment où vous devez vous assurer quil fonctionne toujours avec nimporte quelle entrée.

Même sans les instructions echo pour vous montrer ce qui se passe, vous pouvez voir que ce code est déjà plus long que les exemples de lautre réponse qui montrent comment le faire correctement. Donc, en nutilisant pas un outil tiers, vous vous donnez plus de code à écrire, ce qui vous prendra plus de temps à écrire et à déboguer, et vous vous retrouvez également avec une solution moins flexible et qui va pause quand il rencontre quelque chose dinattendu.

Commentaires

  • cétait assez informatif – peut ‘ t comprendre pourquoi les gens voteraient contre

Réponse

Alternativement, vous pouvez utiliser un Unix basé sur un chemin de marche utilitaire jtc :

id="{"name":"john"}" bash $ key=$(jtc -w"[0]<>k" <<<"$id") bash $ echo $key "name" bash $ value=$(jtc -w"[0]" <<<"$id") bash $ echo $value "john" bash $ 

PS> Divulgation: Je « suis le créateur de loutil jtc – shell cli pour les opérations JSON

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *