Salut,
J'ai une question a propos du fonctionnement du Shell.
Pourquoi la redirection suivante ne fonctionne pas:
Lorsque j'affiche mon fichier file.txt il est vide ! Pourquoi ?Code:cat file.txt | sed 's/abc/xyz/' > file.txt
Version imprimable
Salut,
J'ai une question a propos du fonctionnement du Shell.
Pourquoi la redirection suivante ne fonctionne pas:
Lorsque j'affiche mon fichier file.txt il est vide ! Pourquoi ?Code:cat file.txt | sed 's/abc/xyz/' > file.txt
Parce que le shell, en analysant ta ligne, a détecté une redirection. Et il commence alors par préparer le terrain en créant le container vide prêt à recevoir le résultat => ton fichier est alors vidé avant d'être traité
Si tu veux faire ça, il existe une astuce
1) on commence par créer un buffer numéroté associé au fichier. Ainsi, le canal 3 contient les datas du fichierCode:
1
2
3 exec 3<file.txt rm -f file.txt cat 0<&3 | sed -e "s/abc/xyz/" > file.txt
2) on efface le fichier afin de dissocier son nom de son contenu. C'est impératif. Si on ne le faisait pas, le nom "file.txt" serait toujours associé à son contenu et vider "file.txt" viderait son contenu.
Inversement, si on l'efface, ça libère le nom "file.txt" qui disparait du répertoire et qui peut donc être réutilisé. Et le contenu d'origine est toujours présent, mais maintenant associé au canal 3
3) on traite le canal 3 (le contenu initial) et on écrit les datas dans un nouveau fichier "file.txt".
Accessoirement, le cat est inutile. Autant éviter de générer des processus pour rien...
Code:sed -e "s/abc/xyz/" 0<&3 >file.txt
Merci pour cette explication et cette solution
Sur la plupart des UNIX, au moins GNU et BSD libres, il existe surtout l'option -i (inplace) qui sert à cela. Mais il est toujours bon de savoir comment gérer les flux d'une manière générale.
sed -i 's/abc/xyz/' file.txt
Mouais. Je ne connaissais pas. Mais présenté comme ceci, il semblerait que l'option "-i" n'a été mise en place que dans le sed.
Et donc si le pb avait eu lieu sur une commande "awk" ou "tr" on aurait pas pu l'utiliser non ?
C'est toujours bon à savoir bien entendu. Mais je préfère ma solution qui a l'avantage d'être portable et d'être adaptable à tout programme de traitement et à laquelle je me suis habitué ;)
C'est comme en Python. Pendant des années, j'ai simulé le ternaire de la façon suivante: var=booléen and v1 or v2 (dangereux si v1 vaut 0) et j'ai découvert récemment une syntaxe plus adaptée var=v1 if booléen else v2 (fiable à 100%).
Ben j'ai énormément de mal, quand je dois mettre un ternaire, à utiliser la seconde expression...8-)
Pour éviter ce genre de souci, il peut être bon d'utiliser perl en ligne...