IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Redirection vs pipe pour traiter une chaine


Sujet :

Shell et commandes GNU

  1. #1
    Rédacteur


    Homme Profil pro
    Instituteur retraité
    Inscrit en
    Novembre 2015
    Messages
    891
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Instituteur retraité
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2015
    Messages : 891
    Points : 4 157
    Points
    4 157
    Billets dans le blog
    1
    Par défaut Redirection vs pipe pour traiter une chaine
    Bonjour,

    Pour traiter une chaine de caractères, il est généralement possible d'utiliser une redirection ou un pipe.
    Exemple, pour extraire les chiffres d'une chaine de caractères
    par un pipe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     echo "$chaine" | sed 's/[^[:digit:]]//g'
    par une redirection
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo $(sed 's/[^[:digit:]]//g' <<<"${chaine}")
    N'étant pas un spécialiste, je serais curieux de savoir si une méthode est préférable à une autre, et pourquoi.
    Merci d'avance pour vos éclairages.
    Plus on apprend, plus on découvre que ce que l'on sait est insignifiant face à tout ce que l'on ne sait pas.
    Retrouvez la liste de mes articles et tutoriels sur la sauvegarde-restauration, les distributions éducatives, le système Linux et le Raspberry pi en cliquant sur ce lien.

  2. #2
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 389
    Points
    19 389
    Par défaut
    Bonjour,

    dans le cas présent, aucun avantage pour une méthode ou l'autre.
    par contre, l'emploi d'une substitution de commande est inutile :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed 's/[^[:digit:]]//g' <<<"${chaine}"
    il ne s'agit d'ailleurs pas d'une redirection, mais d'une chaîne en ligne, c'est comme un document en ligne, mais pour une seule chaîne.

    là où ça pourrait avoir du sens, c'est pour l'assignation de variables :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    str="abc def"
    read -r var1 var2 <<<"$str"
    alors que par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo "$str" | read -r var1 var
    ne conservera pas les valeurs de var1 et var2 parce qu'un pipe s'exécute dans un sous shell.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  3. #3
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 563
    Points : 460
    Points
    460
    Par défaut
    C'est hors sujet mais pour cet exemple, on peut le faire en full bash
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    chaine="abc123def"
    echo "${chaine//[^[:digit:]]/}"
    => 123
    Sous Kubuntu 20.04

  4. #4
    Rédacteur


    Homme Profil pro
    Instituteur retraité
    Inscrit en
    Novembre 2015
    Messages
    891
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Instituteur retraité
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2015
    Messages : 891
    Points : 4 157
    Points
    4 157
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par hizoka Voir le message
    C'est hors sujet mais pour cet exemple, on peut le faire en full bash
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    chaine="abc123def"
    echo "${chaine//[^[:digit:]]/}"
    => 123
    C'est toujours utile d'indiquer comment il est possible de faire les choses plus simplement !
    Plus on apprend, plus on découvre que ce que l'on sait est insignifiant face à tout ce que l'on ne sait pas.
    Retrouvez la liste de mes articles et tutoriels sur la sauvegarde-restauration, les distributions éducatives, le système Linux et le Raspberry pi en cliquant sur ce lien.

  5. #5
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 458
    Points
    13 458
    Par défaut
    Bonjour

    Ce que décrit Philippe Dpt35 est le réflexe général des informaticiens: toujours mettre les trucs dans une variable. Mais sous Linux, ne dit-on pas que "tout est fichier" ?

    Il n'y a pas 2 choses. Mais 3: La chaîne de caractère, le fichier dans un pipe, et le fichier redirigé.

    Rappel: le pipe n'est qu'une double redirection qui évite de créer un fichier temporaire
    exe1 >tmp;exe2 <tmp est équivalent à exe1 | exe2.



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     echo "$chaine" | sed 's/[^[:digit:]]//g'
    Cette ligne est bizarre. On transforme une variable en fichier pour la traiter. Le "echo" est superfétatoire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo $(sed 's/[^[:digit:]]//g' <<<"${chaine}")
    Ici, on alimente bien sed par une variable et sa sortie est un fichier qu'on transforme en variable par l'opérateur $( ) pour le soumettre à "echo" qui va sortir un fichier.
    Pourquoi faire simple quand on peut faire compliqué ?

    De plus, ces transformations ne sont jamais anodines. Évidemment, si on a un fichier d'une seule ligne, c'est transparent. Mais sinon, que deviennent les retours à la ligne ? Et echo, va-t-il interpréter les caractères échappés ? Veut-on toujours les interpréter dans la ligne ?

    Perso, je déconseillerais de passer par bash pur si c'est juste pour faire de la modification de fichiers texte, si ce n'est pas utile. grep/sed/awk conviennent bien.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  6. #6
    Rédacteur


    Homme Profil pro
    Instituteur retraité
    Inscrit en
    Novembre 2015
    Messages
    891
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Instituteur retraité
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2015
    Messages : 891
    Points : 4 157
    Points
    4 157
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    Bonjour

    Ce que décrit Philippe Dpt35 est le réflexe général des informaticiens: toujours mettre les trucs dans une variable. Mais sous Linux, ne dit-on pas que "tout est fichier" ?

    De plus, ces transformations ne sont jamais anodines. Évidemment, si on a un fichier d'une seule ligne, c'est transparent. Mais sinon, que deviennent les retours à la ligne ? Et echo, va-t-il interpréter les caractères échappés ? Veut-on toujours les interpréter dans la ligne ?

    Perso, je déconseillerais de passer par bash pur si c'est juste pour faire de la modification de fichiers texte, si ce n'est pas utile. grep/sed/awk conviennent bien.
    Je précise que je n'ai utilisé echo que pour le test en ligne de commande.
    L'utilisation d'une variable est contraint si on ne travaille pas sur un fichier, mais sur des noms de fichiers que l'on explore par exemple.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for fichier in "$repertoire"/*.ext ; do
        nom_fichier=$(basename "$fichier")
        nombre=$(sed 's/[^[:digit:]]//g' <<< "${nom_fichier}")
       .....
    done
    Ce qui m'intéressait était de savoir s'il convenait de privilégier les redirections ou les pipes quand on avait le choix, et pourquoi.
    Là, en l'occurrence, on pouvait très simplement utiliser du bash pur, comme l'a signalé hizoka.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
           nombre=${nom_fichier//[^[:digit:]]/}
    Plus on apprend, plus on découvre que ce que l'on sait est insignifiant face à tout ce que l'on ne sait pas.
    Retrouvez la liste de mes articles et tutoriels sur la sauvegarde-restauration, les distributions éducatives, le système Linux et le Raspberry pi en cliquant sur ce lien.

  7. #7
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 389
    Points
    19 389
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nom_fichier="${fichier##*/}"
    et hop ! encore une commande externe de plus en moins
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  8. #8
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 458
    Points
    13 458
    Par défaut
    Ben là, par exemple, je ne fais pas un "for" sur les fichiers car la moindre espace dans les noms de fichiers et c'est le drame: bug.
    On fera plutôt un find. Et à moins de faire find -exec, la sortie de find est un fichier qui contient la liste des fichiers.

    On préfèrera les pipes aux redirections puisque le pipe est là pour éviter une redirection vers un fichier temporaire.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  9. #9
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 389
    Points
    19 389
    Par défaut
    Ben là, par exemple, je ne fais pas un "for" sur les fichiers car la moindre espace dans les noms de fichiers et c'est le drame: bug.
    meuh non. il suffit de bien prendre soin de mettre les variables entre guillemets.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  10. #10
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 458
    Points
    13 458
    Par défaut
    Oui: Mais dans l'exemple de notre ami, le soin n'a pas été pris. Et moi, je suis aussi peu soigneux que lui.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  11. #11
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 389
    Points
    19 389
    Par défaut
    le soin a bien été pris, regarde soigneusement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for fichier in "$repertoire"/*.ext ; do
        nom_fichier=$(basename "$fichier")
        nombre=$(sed 's/[^[:digit:]]//g' <<< "${nom_fichier}")
       .....
    done
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    var="./mon fichier" 
    var1=$(basename "$var")
    echo "$var1"
    mon fichier
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  12. #12
    Inactif  
    Homme Profil pro
    Architecte matériel
    Inscrit en
    Décembre 2017
    Messages
    155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Architecte matériel

    Informations forums :
    Inscription : Décembre 2017
    Messages : 155
    Points : 0
    Points
    0
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    Mais sous Linux, ne dit-on pas que "tout est fichier" ?
    Oui on dit des tas de choses ineptes. Surtout les cuistres!

    Citation Envoyé par N_BaH Voir le message
    Attention!

    La commande echo (aussi bien le binaire exécutable /bin/echo que la commande intégrée) acceptent de nombreuses options comme "-E".

    Donc si $str a une de ces valeurs, ça ne marchera pas!

    Donc echo "$str" n'est pas bon sauf si on a restreint les valeurs possibles de $str.

    Citation Envoyé par N_BaH Voir le message
    meuh non. il suffit de bien prendre soin de mettre les variables entre guillemets.
    Non, il suffit d'utiliser le seul bon shell (zsh).

    Citation Envoyé par Flodelarab Voir le message
    Ben là, par exemple, je ne fais pas un "for" sur les fichiers car la moindre espace dans les noms de fichiers et c'est le drame: bug.
    On fera plutôt un find. Et à moins de faire find -exec, la sortie de find est un fichier qui contient la liste des fichiers.
    Et le moindre nom de fichier qui contient un retour à la ligne... et c'est le drame!

  13. #13
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 458
    Points
    13 458
    Par défaut
    le soin a bien été pris, regarde soigneusement :
    Oui! Au temps pour moi. Je confonds toujours for fichier in * avec for fichier in $(ls). Le premier est bon, l'autre horrible.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

Discussions similaires

  1. sizeof dans une fonction pour lire une chaine
    Par Haze. dans le forum Débuter
    Réponses: 11
    Dernier message: 06/11/2007, 12h07
  2. [Débutant] Traiter une chaîne de caractères
    Par jacques64 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 23/08/2007, 12h08
  3. Macro pour traiter une colonne en relatif
    Par jacques64 dans le forum Macros et VBA Excel
    Réponses: 14
    Dernier message: 14/06/2007, 12h53
  4. Recherche méthode pour formater une chaine pour JS
    Par mittim dans le forum Langage
    Réponses: 1
    Dernier message: 05/09/2006, 10h04
  5. [langage] cherche script pour formater une chaine
    Par MASSAKA dans le forum Langage
    Réponses: 7
    Dernier message: 12/11/2003, 12h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo