# \[shell posix\] afficher une chaine avec ses backslashs

**URL:** <https://www.debian-fr.org/t/shell-posix-afficher-une-chaine-avec-ses-backslashs/31999>\
**Category:** Programmation\
**Created:** [Février 21, 2016, 1:51 UTC](https://www.debian-fr.org/t/shell-posix-afficher-une-chaine-avec-ses-backslashs/31999 "2016-02-21T01:51:16Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![branch](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/b/ee7513/32.png) [@branch](https://www.debian-fr.org/u/branch)\
**Post date:** [Février 21, 2016, 1:51 UTC](https://www.debian-fr.org/t/shell-posix-afficher-une-chaine-avec-ses-backslashs/31999/1 "2016-02-21T01:51:16Z")

</div>

Bonjour,

J’essaye de faire une fonction qui puisse afficher une chaine de caractères sans effacer les backslashs, et en faisant une action sur chaque ligne (délimitées par des retours chariots).

Pour l’instant j’ai fait ça :

`afficher() {
  chaines="$1"
  while read une_chaine; do
    echo voila une chaine "$une_chaine"
  done <<delimiter
$chaines
delimiter
}`

Mais le problème est que si l’argument passé à la fonction contient un backslash, il est supprimé :

`$ chaine='\a
\b'
$ echo "$chaine"
\a
\b
$ afficher "$chaines"
voila une chaine a
voila une chaine b`

Connaissez-vous une astuce pour empêcher le shell de mettre le bazard dans les chaînes de caractères ?

---

<div class="post-metadata">

**Author:** ![valrik](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/v/db5fbb/32.png) [@valrik](https://www.debian-fr.org/u/valrik)\
**Post date:** [Février 21, 2016, 1:51 UTC](https://www.debian-fr.org/t/shell-posix-afficher-une-chaine-avec-ses-backslashs/31999/2 "2016-02-21T01:51:27Z")

</div>

bonjour à tous,  
si tu as la main sur le format de sortie des messages tu peux doubler le caractère d’échappement :

` :-) $ afficher '\\A'
voila une chaine \A
 :-) $ 
`  
Car le caractère d’échappement du caractère d’échappement est… le caractère d’échappement ! 😉  
Dans le cas contraire, on peut imaginer un doublement par une commande “sed” via des tubes du genre :

```auto
l'appli_qui_sort_le_\ | une_commande_sed_qui_double_les_\ | afficher
```

Après, je ne connais pas d’option à echo ou printf permettant de faire ce que tu veux. Cela ne veux pas dire qu’elle n’existe pas…  
Dans tous les cas on peut tester dans le script “afficher” caractère par caractère, mais pour des fichiers volumineux, cela risque de consommer beaucoup de ressource système… Une petit programme en C serait le bien venu… 😉

---

<div class="post-metadata">

**Author:** ![branch](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/b/ee7513/32.png) [@branch](https://www.debian-fr.org/u/branch)\
**Post date:** [Février 21, 2016, 1:51 UTC](https://www.debian-fr.org/t/shell-posix-afficher-une-chaine-avec-ses-backslashs/31999/3 "2016-02-21T01:51:29Z")

</div>

Merci ! Ce n’est pas bête du tout ça de doubler les basckslashs.

Mais j’aimerai une solution plus universelle (qui marche aussi pour les étoiles) :

`afficher() {
  chaine='$'"$1"
  for ligne in $( eval "echo \"\"$chaine\"\"" ); do
    echo une ligne "$ligne"
  done
}`

Ca marche presque : mais il y a encore les étoiles qui sont remplacées par le contenu du répertoire :

[code]$ chaine=’\a  
\b  
\*

* * *

\*  
$abcd  
$abcd’[/code]

```auto

```

---

<div class="post-metadata">

**Author:** ![valrik](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/v/db5fbb/32.png) [@valrik](https://www.debian-fr.org/u/valrik)\
**Post date:** [Février 21, 2016, 1:53 UTC](https://www.debian-fr.org/t/shell-posix-afficher-une-chaine-avec-ses-backslashs/31999/4 "2016-02-21T01:53:46Z")

</div>

Mais quel est ton but exactement ?  
Car si tu souhaites faire des traitements ligne par ligne (même un tout bête affichage), les commandes sed ou awk sont vraiment faites pour cela.  
Le shell (bash ?) n’est pas trés maniable pour les cas complexes… ☹

---

<div class="post-metadata">

**Author:** ![branch](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/b/ee7513/32.png) [@branch](https://www.debian-fr.org/u/branch)\
**Post date:** [Février 21, 2016, 1:53 UTC](https://www.debian-fr.org/t/shell-posix-afficher-une-chaine-avec-ses-backslashs/31999/5 "2016-02-21T01:53:48Z")

</div>

> [@valrik](#):
>
> Le shell (bash ?) n’est pas trés maniable pour les cas complexes… ☹

Oui … c’est vraiment pas pratique. En fait, plus j’apprends le shell et plus je déteste ce langage. Impossible d’affecter le contenu d’une variable à une autre sans que ce contenu soit «&nbsp;interprété&nbsp;» à tout va. Vraiment insupportable, on ne peut pas faire un code qui tienne la route.

Il faut que je me trouve un langage de scripts qui, bien qu’interprété, fournissent des variables dignes de ce nom. Et qui ne modifie des trucs que lorsqu’on le demande.

Je ne m’étais jamais posé la question avant, mais là je me demande vraiment pourquoi cette horreur sert de langage de script de base sur tout les systèmes Unix du monde. A moins d’être un expert, c’est un nid à bugs.

Bon après avoir vidé mon sac, je réponds à ta question : mon but est d’arriver à manipuler des variables comme on le ferait dans n’importe quel langage de programmation normal. C’est à dire en maîtrisant le contenu d’une chaîne de caractères à l’octet près. Mais j’abandonne, car même si j’arrivais à faire cette prouesse, si jamais je fais un «&nbsp;echo&nbsp;» du contenu de la variable, tout est modifié.

En tout cas merci d’avoir essayer de résoudre mon problème insoluble.

* * *

Au fait pour sed et awk, il y a toujours le même problème, au moment de passer les données à traiter à ces langages, il y aura une expansion faite par le shell. En fait, il faut toujours laisser les données dans des fichiers et les manipuler avec des commandes pour assurer leur intégrité. Donc pour résumer, les variables du shell sont stockées sur le disque dur (c’est pas terrible au niveau des perfs).

* * *

Yeah !! ![:115](https://www.debian-fr.org/uploads/default/original/1X/f0b4ead290aa124671b5f77e5c5e1073057a630b.gif "eureka") ![:115](https://www.debian-fr.org/uploads/default/original/1X/f0b4ead290aa124671b5f77e5c5e1073057a630b.gif "eureka") ![:115](https://www.debian-fr.org/uploads/default/original/1X/f0b4ead290aa124671b5f77e5c5e1073057a630b.gif "eureka") J’ai trouvé la solution pour faire des trucs potables : stocker le contenu des variables dans des fichiers se trouvant dans le répertoire [size=110]/dev/shm[/size] !

Comme ça on a les perfs et la sûreté. ![:041](https://www.debian-fr.org/uploads/default/original/1X/bfe857c9119752799c3eac55ca37a50312c51282.gif "applaudit")

---

<div class="post-metadata">

**Author:** ![valrik](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/v/db5fbb/32.png) [@valrik](https://www.debian-fr.org/u/valrik)\
**Post date:** [Février 21, 2016, 1:53 UTC](https://www.debian-fr.org/t/shell-posix-afficher-une-chaine-avec-ses-backslashs/31999/6 "2016-02-21T01:53:49Z")

</div>

[quote]Je ne m’étais jamais posé la question avant, mais là je me demande vraiment pourquoi cette horreur sert de langage de script de base sur tout les systèmes Unix du monde. A moins d’être un expert, c’est un nid à bugs.  
[/quote]  
En fait le shell, n’est pas prévu pour traiter des bases de données, même sous forme de fichier plat. Son rôle se borne à une interface utilisateur / noyau (en gros).

> [@](#):
>
> Oui … c’est vraiment pas pratique. En fait, plus j’apprends le shell et plus je déteste ce langage. Impossible d’affecter le contenu d’une variable à une autre sans que ce contenu soit «&nbsp;interprété&nbsp;» à tout va. Vraiment insupportable, on ne peut pas faire un code qui tienne la route.

Vois-tu, on ne peut pas en vouloir au shell d’interpréter des commandes et des variables, c’est tout de même sont but premier ! 😉  
Si tu veux interpréter de façon efficace un fichier plat avec des champs un peu biscornus, c’est awk qu’il te faut. Une commande awk s’intègre parfaitement dans un script shell. Il y a des tas de tutos sur le net.  
Une dernière chose : il existe une commande basic d’extraction de chaîne dans le shell. C’est ${}

` :-) $ var="AZERTYUIOP"
 :-) $ printf "${var#AZE}\n"
RTYUIOP
 :-) $ var="AZERT\YUIOP"
 :-) $ printf "${var#AZE}\n"
RT\YUIOP
 :-) $ 
`  
Il y a d’autres caractères de contrôle que tu trouvera sans doute facilement sur internet. Les tutos ne manquent pas. ![:041](https://www.debian-fr.org/uploads/default/original/1X/bfe857c9119752799c3eac55ca37a50312c51282.gif "applaudit")

Pour awk, je crois que j’ai des liens dans ma besace… Si ça t’intéresse…  
[http://www.bruno-garcia.net/www/Unix/Docs/awk.html](http://www.bruno-garcia.net/www/Unix/Docs/awk.html)  
[http://sunsite.ualberta.ca/Documentation/Gnu/gawk-3.0.6/html\_chapter/gawk\_toc.html#SEC\_Contents](http://sunsite.ualberta.ca/Documentation/Gnu/gawk-3.0.6/html_chapter/gawk_toc.html#SEC_Contents)

---

<div class="post-metadata">

**Author:** ![branch](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/b/ee7513/32.png) [@branch](https://www.debian-fr.org/u/branch)\
**Post date:** [Février 21, 2016, 1:53 UTC](https://www.debian-fr.org/t/shell-posix-afficher-une-chaine-avec-ses-backslashs/31999/7 "2016-02-21T01:53:52Z")

</div>

Merci pour les liens, oui awk m’intéresse. J’avais déjà lu le man mais un cours plus complet est indispensable.  
L’extraction de chaîne est bien utile aussi, ça me permettra souvent de me passer de grep.

J’ai poussé les recherches sur le site de l’[opengroup](http://pubs.opengroup.org/onlinepubs/9699919799/) et j’ai réussi à trouver des techniques pour désactiver certaines expansions :

1. Désactiver la décomposition du résultat des commandes en éléments afin de préserver les espaces. Il faut mettre la variable IFS égal à la chaine vide ‘’. Voir [posix shell field splitting](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05).

2. Utiliser l’option -r de la commande read permet de considérer les backslashs comme des caractères normaux. Voir [posix shell read utility](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html).

3. Les backslashs \ , quotes ’ et guillemets " sont toujours supprimés lors de l’évaluation d’une instruction, sauf s’ils sont échappés avec un backslash \ , ou avec des quotes ’ , ou avec des guillemets ". Voir [posix shell quote removal](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_07).  
Voici la commande sed qui permet de rajouter un backslash devant toutes les occurences de ces trois caractères :

```auto

```

1. La commande echo ne permet pas de gérer les backslashs de manière portable. Il faut utiliser printf à la place. Elle permet un contrôle beaucoup plus fin de ce qui est affiché. Voir [posix shell echo utility](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16) et [posix shell printf utility](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html)

* * *

En fait je viens de me rendre compte que tu m’as donné la solution pour mon problème initial. Pour afficher une chaine avec ses backslashs :

`printf '%s\n' "$ma_chaine"` ![:obscene-hanged:](https://www.debian-fr.org/uploads/default/original/1X/c88e3b5d6e57915cf3e9f1e03ae436834cca2571.gif "Hanged")
