Journal Écrire du JSON dans un script bash

Posté par  .
Étiquettes : aucune
9
13
oct.
2026

J'ai toujours galéré à quoter et échapper correctement les chaînes de caractères compliquées avec bash, donc je me suis dit que j'allais (enfin) regarder la doc.

Je parle de JSON dans le titre, qui est particulièrement pénible car il contient beaucoup de guillemets, mais ça s'applique aussi aux quotes l'une dans l'autre, typiquement quand on veut exécuter une sous-commande. Par exemple un one-liner dans un autre langage de programmation, ou une commande avec ssh ou un sous-shell.

Commençons par regarder les 4 mécanismes de quoting intéressants dans bash, on passera ensuite à des exemples.

Les mécanismes

1. Les apostrophes

C'est le plus simple à expliquer : tout ce qui est entre des apostrophes est traité comme un caractère normal, à l'exception d'un \ suivi d'un retour à la ligne, qui ignore ce retour à la ligne.

Une conséquence pénible de ce fonctionnement est qu'il est impossible de mettre une apostrophe dans ce type de chaîne. Une façon moche de contourner ça est de fermer l'apostrophe, l'échapper puis la rouvrir :

echo 'l'\''animal'

A noter que la commande echo de zsh interprète par défaut les caractères d'échappement commençant par \, ce qui peut donner à tort l'impression que les chaînes entre apostrophes le font.

2. les guillemets

Ils interprètent les séquences commençant par $ (variables, etc.), les séquences avec \ et les apostrophes inversées (commandes).

C'est souvent le plus pratique, mais l'inconvénient est que pour les formats comme le JSON, il faut échapper beaucoup de guillemets.

3. Le quoting ANSI-C

Celui-ci je ne le connaissais pas : c'est la même chose que les guillemets simples, mais il interprète les séquences en \ :

echo $'l\'animal'

C'est vraiment pratique, car ça permet de faire la même chose que des guillemets simples, mais avec la possibilité de mettre des guillemets simples facilement, ou d'autres caractères spéciaux comme les tabulations ou les retours à la ligne.

4. Les here docs

Ce n'est pas un mécanisme de quoting, mais sert à indiquer une chaîne de caractères qui va être envoyé sur stdin. Il est très pratique pour des chaînes de caractères de plusieurs lignes, et on peut tricher pour l'utiliser pour le quoting :

# Ecrit le here document dans fichier.txt
cat > fichier.txt <<EOF
Ligne 1
Ligne 2
EOF

# On triche pour le quoting
echo $(<<EOF
Ligne 1
Ligne 2
EOF
)

À noter que EOF est une chaîne de caractères arbitraire : on peut utiliser n'importe quelle chaîne qui ne sera pas une ligne du here document.

En pratique

Sans variables

Admettons que l'on veuille consulter une API de météo. Commençons par la façon pénible de faire :

curl --json '{"city": "L'\''Isle d'\''Abeau"}' https://example.com/weather

Maintenant, avec ce qu'on a appris on peut utiliser le quoting ANSI-C :

curl --json $'{"city": "L\'Isle d\'Abeau"}' https://example.com/weather

Ou les here documents :

curl --json @- https://example.com/weather <<EOF
{"city": "L'Isle d'Abeau"}
EOF

Note : @- est une option spécifique à curl lui disant de lire les données sur stdin.

Avec des variables

Commençons cette fois-ci aussi par la façon pénible de faire. Vu qu'on ne peut pas utiliser des variables avec des apostrophes, utilisons des guillemets :

curl --json "{\"city\":\"$CITY\"}" https://example.com/weather

On peut faire mieux avec un here document :

curl --json @- https://example.com/weather <<EOF
{"city": "$CITY"}
EOF

Ou avec des guillemets simples et printf :

printf '{"city":"%s"}' "$CITY" | curl --json @- https://example.com/weather

Ou, si on veut une solution qui marche avec une ville arbitraire pouvant contenir des guillemets dans son nom :

jq -n '{city: $CITY}' --arg CITY "$CITY" | curl --json @- https://example.com/weather
  • # Bash

    Posté par  (site web personnel, Mastodon) . Évalué à -2 (+5/-9).

    Si je puis me permettre, Bash est hasbeen. J'entends bien que bash est indispensable, mais il doit être réduit au minimum (lancement basic de l'application dans son environnement, quelques commandes d'init au besoin). Après il faut passer au Perl ou, plus moderne, Python. En fait je dirais même que Bash est à réservé pour l'admin sys.

    Clairement Bash est une horreur et pas seulement pour les chaines de caractères, mais aussi pour les conditions. Non seulement, c'est plus simple de s'en passer quand on peut, mais aussi c'est plus sécurisé. Combien de fois un script bash qui fonctionnait bien se met à planter à cause d'un paramètre, ou un chemin avec un accent, un espace, un dollar… quand ce n'est pas un hacker qui l'exploite.

    Sous licence Creative common. Lisez, copiez, modifiez faites en ce que vous voulez.

    • [^] # Re: Bash

      Posté par  . Évalué à 10 (+11/-0).

      Autant je suis d'accord que bash est inadapté à des scripts trop compliqués et qu'il a beaucoup de footguns, autant il a deux avantages très importants :

      • Il est installé partout
      • Il permet de passer très facilement de commandes lancées manuellement dans un terminal à un script

      Pour les footguns, shellcheck est un très bon linter et permet d'identifier facilement la plupart des commentaires.

      Quant à la remarque "Bash est hasbeen", je ne sais pas quoi y répondre vu que dans la foulée tu proposes d'utiliser Perl.

      • [^] # Re: Bash

        Posté par  (site web personnel) . Évalué à 4 (+2/-0). Dernière modification le 13 octobre 2026 à 21:36.

        Et puis Bash n'est pas du tout has been. Il est même très intéressant dans de nombreux cas. Il ne faut juste pas mélanger les usages. C'est clair que shellcheck fait un super boulot pour éviter certaines formes pas top.

        Cependant, pour l'admin système, heureusement qu'il est là avec un écosystème bien stable.

        Pour faire aussi du PowerShell sous Windows, un langage de script ne remplace pas un langage de shell dans tous les domaines, et PowerShell est plus un langage de script avec l'espace comme séparateur que de shell à mon sens.

      • [^] # Re: Bash

        Posté par  (site web personnel, Mastodon) . Évalué à 3 (+1/-0).

        C'est exactement ce que je veux dire. Hasbeen est exagéré, mais je voulais dire que je n'irais pas géré des chaînes de caractères complexe en bash.

        Même si pour certains cas, on aime bien avoir un script qu'on peut lancer partout (Linux ou Unix) et que Python (ou autre) n'est pas toujours disponible ni dans la version compatible ou encore avec les libs… Mais c'est rare.

        Sous licence Creative common. Lisez, copiez, modifiez faites en ce que vous voulez.

    • [^] # Re: Bash

      Posté par  (site web personnel) . Évalué à 6 (+5/-1).

      Après il faut passer au Perl ou, plus moderne, Python.

      Phrase typique que te sors une IA.

      Si tu la titilles un peu, pourquoi Python est plus moderne que Perl, en pratique, elle sèche assez vite. Voire il est facile de faire dire à l'IA qu'au final, non, tu as raison, il vaut mieux faire en Perl qu'en Python.

      Juste pour dire que c'est amusant ce genre de chose que tout le monde répète, mais sans forcément de fondement réel.

      • [^] # Re: Bash

        Posté par  (site web personnel, Mastodon) . Évalué à 2 (+1/-1).

        Si il y a un fondement : les côtes de popularité. Après ça vaut ce que cela vaut, mais sommes toute on a plus de Perl convertit en Python que l'inverse. Cf les distributions.

        PS : ce n' est pas de l'IA.

        Sous licence Creative common. Lisez, copiez, modifiez faites en ce que vous voulez.

      • [^] # Re: Bash

        Posté par  (Mastodon) . Évalué à 4 (+1/-0). Dernière modification le 14 octobre 2026 à 00:21.

        Je ne suis pas fan de python, si je veux utiliser un langage lent, autant utiliser ruby qui est au moins agréable et pas moche mais dans le cas concret du json dans un script un peu de pragmatisme que diable! Entre perl et python j'aurai tendance à choisir ce dernier car le module json est dans la stdlib et tu n'as pas besoin de gérer des dépendances et des risques de chaîne d'approvisionnement.

        Et c'est vrai que sans vouloir basher bash, c'est un peu sado-masochiste et vouloir du code bogué de l'utiliser pour manipuler du json.

        Je n'utilise pas un marteau pour serrer un écrou.

    • [^] # Re: Bash

      Posté par  (site web personnel) . Évalué à 5 (+3/-0).

      En fait je dirais même que Bash est à réservé pour l'admin sys.

      Non les adminsys aussi sont pour l'interdiction de se faire torturer !

      Adhérer à l'April, ça vous tente ?

      • [^] # Re: Bash

        Posté par  (site web personnel, Mastodon) . Évalué à 5 (+2/-0).

        Même pas un tout petit peu ?

        Je n’ai aucun avis sur systemd

        • [^] # Re: Bash

          Posté par  (site web personnel) . Évalué à 4 (+2/-0). Dernière modification le 13 octobre 2026 à 21:45.

          Il y a certaines personnes, qui, effectivement, nourrissent leur ego (voire tirent une certaine gloire pendant les récits d'exploit au comptoir) de se sentir de temps à autre victorieux de ce perpétuel combat entre l'homme et la machine. Et les (plus nombreuses) fois où ils ont perdu la bataille face à la machine fait sans doute le sel de leur métier-passion.

          Adhérer à l'April, ça vous tente ?

        • [^] # Re: Bash

          Posté par  . Évalué à 4 (+2/-0).

          Mais si, il y en a qui utilisent 'vi'…

    • [^] # Re: Bash

      Posté par  . Évalué à 8 (+5/-0).

      les gens modernes utilisent shellcheck (ou un truc du genre)

      l'intérêt du bash c'est qu'on peut facilement déléguer les différentes tâches a des langages plus appropriés, typiquement sed ou perl selon la complexité du flux à traiter.

      Dans la cas présent j'aurais joué avec jq

      jq --null-input --arg ville "L'isle D'Abeau"  '{"city": $ville}'

      Le python devient excessivement chiant lorsque l'on veut déléguer à une autre commande ce qui pousse à tout faire avec,

      Il ne faut pas décorner les boeufs avant d'avoir semé le vent

    • [^] # Re: Bash

      Posté par  . Évalué à 7 (+6/-0).

      Sur un parc qui va de RHEL 4 à RHEL 10, Perl ou Python deviennent vite pénibles (versions d’interpréteur, modules manquants…). Avec Bash, on a nettement moins de modifications à faire. Ça ne le rend pas moins horrible pour les chaînes et les conditions, mais pour du glue d’admin système, il reste souvent le choix pragmatique — à condition de s’imposer une hygiène de programmation stricte.

      • [^] # Re: Bash

        Posté par  (Mastodon) . Évalué à 9 (+6/-0).

        Honnêtement c'est un très mauvais argument: Un script perl 5 écrit il y a 25 ans fonctionne toujours aunourd'hui sous perl 5.44. S'il y a un truc qu'on ne peut pas enlever à perl c'est sa stabilité et compatibilité ascendante. C'est une des raisons qui l'ont fait abandonner perl 6 pour créer raku.

        Et sous python le seul saut majeur entre rhel 4 et 10 a été le passage de python 2 à python 3. Et honnêtement c'était surtout un problème pour des projets python qui utilisaient beaucoup de dépendances pip dont l'agenda de migration n'était pas coordonné.

        Dans les faits si tu écrits des scripts perl ou python pour du système tu te limites au maximum à la stdlib et évite les cascades de dépendances á des modules cpan ou pip donc ce genre de problème ne se pose pas. On est à des années lumières d'un package.json nodejs. Une migration unique en 30ans, ce n'est pas la mer á boire. Surtout que le shebang est contrôlé, que les distrib ont maintenu deux versions majeures en parallèle pendant plusieurs années et qu'il a toujours été trivial d'embarquer son propre perl ou python indépendant de la version de la distrib.

  • # Here-doc et pipe sur les deux derniers exemples

    Posté par  . Évalué à -8 (+2/-7).

    Les deux derniers exemples ont un <<EOF sans corps, après le pipe. @- lit le stdin de curl, et ce here-doc le remplace : le JSON du printf ou de jq n’arrive pas. Sans le <<EOF, le pipe suffit.

  • # Commentaire supprimé

    Posté par  . Évalué à -4 (+0/-4). Dernière modification le 16 octobre 2026 à 20:14.

    Ce commentaire a été supprimé par l’équipe de modération.

    • [^] # Re: Quelques compléments sur les here docs

      Posté par  . Évalué à 5 (+2/-0).

      Tien encore une IA qui ne sait pas que rm -rf / ne fait strictement rien :)

      pour le reste ça reste indigeste et les $ sont partis au formatage, ce qui rends cette participation de bot encore plus inutile.

      Il ne faut pas décorner les boeufs avant d'avoir semé le vent

      • [^] # Re: Quelques compléments sur les here docs

        Posté par  . Évalué à 3 (+1/-0). Dernière modification le 16 octobre 2026 à 17:38.

        "100% IA" d'après Pangram mais ce bot parvient tout de même à se faire plusser : https://linuxfr.org/forums/linux-debutant/posts/installation-de-linux-mint#comment-2036498

        Franchement sur ce message je pourrais facilement me faire avoir parce que ça ressemble tout à fait à quelque chose que j'aurais pu écrire.

        • [^] # Re: Quelques compléments sur les here docs

          Posté par  . Évalué à 4 (+1/-0).

          Ben là c'était facile, y'a pas un $ qu'est passé donc tout ce qu'il dit ou presque ne marche pas.

          J'ajouterai qu'il a posté hors des fil existants, que c'est une juxtaposition de diverses recommandations, puis pour pas être méchant et moinssé un inconnu potentiellement nouveau venu pour suspicion d'IA j'ai été voir le profil.

          Bon inutile de dire que mes doutes ont été confirmés dans la foulée.

          J'imagine qu'il fait cela pour tenter de débloquer la possibilité de publication pour nous refourguer sa came

          Il ne faut pas décorner les boeufs avant d'avoir semé le vent

          • [^] # Re: Quelques compléments sur les here docs

            Posté par  (site web personnel) . Évalué à 3 (+1/-0).

            J'imagine qu'il fait cela pour tenter de débloquer la possibilité de publication pour nous refourguer sa came

            moi j'imagine qu'il y a du temps à perdre et à faire perdre. Ce en quoi j'apprécie l'efficacité de la modération à modérer dès qu'il n'y a plus de doute ;-)

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.