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

Linux Discussion :

[bash] Equivalent de la fonction explode en bash ?


Sujet :

Linux

  1. #1
    Membre à l'essai
    Inscrit en
    Septembre 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Septembre 2007
    Messages : 17
    Points : 15
    Points
    15
    Par défaut [bash] Equivalent de la fonction explode en bash ?
    Bonjour à tous !

    Pour les besoins d'un script, je souhaiterais stocker le resultat d'une commande dans une varibale. Ma commade me retourne un chemin. J'aimerais pouvoir acceder à tous les repertoire de ce chemin.
    En plus clair : Soit le resultat de ma commande stocké dans $chemin.
    $chemin est par exemple egal à /etc/tinydns/root/zone
    J'aimerais decouper ma chaine en 4 variables differentes qui contiendrait etc, tinydns, root et zone.
    En php, j'utiliserais $result = explode ("/", $chemin) et ensuite $result[0], $result[1], $result[2] et $result[3]
    Mais en bash, je ne trouve pas d'equivalent a explode

    Merci d'avance

    PS : Au passage, en therorie, je vais me retrouver avec un tableau, comment faire pour connaitre la taille d'un tableau ?

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 720
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 720
    Points : 31 037
    Points
    31 037
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Yein-Yein Voir le message
    Bonjour à tous !

    Pour les besoins d'un script, je souhaiterais stocker le resultat d'une commande dans une varibale. Ma commade me retourne un chemin. J'aimerais pouvoir acceder à tous les repertoire de ce chemin.
    En plus clair : Soit le resultat de ma commande stocké dans $chemin.
    $chemin est par exemple egal à /etc/tinydns/root/zone
    J'aimerais decouper ma chaine en 4 variables differentes qui contiendrait etc, tinydns, root et zone.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    old="$IFS"
    IFS=/
    set "$chemin"
    IFS="$old"
     
    for i in $*
    do
        echo $i
    done
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Membre émérite

    Homme Profil pro
    Expert PHP
    Inscrit en
    Novembre 2004
    Messages
    2 127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Expert PHP
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 127
    Points : 2 557
    Points
    2 557
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    old="$IFS"
    IFS=/
    set "$chemin"
     
    for i in $*
    do
        echo $i
    done
     
    IFS="$old"
    Sinon ça marche pas

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 720
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 720
    Points : 31 037
    Points
    31 037
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Maxoo Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    old="$IFS"
    IFS=/
    set "$chemin"
     
    for i in $*
    do
        echo $i
    done
     
    IFS="$old"
    Sinon ça marche pas
    Ah si, tel que je l'ai écrit (avec le IFS avant le for) ça marche. L'IFS agit sur le set qui va positionner chaque répertoire séparé par "/" dans les paramètres $1, $2, $3 etc. Et le for va les traiter un à un.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Membre émérite

    Homme Profil pro
    Expert PHP
    Inscrit en
    Novembre 2004
    Messages
    2 127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Expert PHP
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 127
    Points : 2 557
    Points
    2 557
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Ah si, tel que je l'ai écrit (avec le IFS avant le for) ça marche. L'IFS agit sur le set qui va positionner chaque répertoire séparé par "/" dans les paramètres $1, $2, $3 etc. Et le for va les traiter un à un.
    Je suis pas un pro du bash, mais j'ai exécuté ton code et ça ne marchait pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/bash
     
    chemin=/etc/tinydns/root/zone
     
    old="$IFS"
    IFS=/
    set "$chemin"
    IFS="$old"
     
    for i in $*
    do
        echo $i
    done
    renvoie cela chez moi :
    /etc/tinydns/root/zone
    Alors que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/bash
     
    chemin=/etc/tinydns/root/zone
     
    old="$IFS"
    IFS=/
    set "$chemin"
     
    for i in $*
    do
        echo $i
    done
    IFS="$old"
    renvoie :
    etc
    tinydns
    root
    zone
    Je ne sais pas trop l'expliquer, comme je te dis, je ne suis pas un pro
    Du coup je pensais que tu t'étais trompé, mais si tu dis que non c'est bizarre.

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 2
    Points : 2
    Points
    2
    Par défaut
    j'ai fait l'essai et trouve comme maxoo.
    a+

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 720
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 720
    Points : 31 037
    Points
    31 037
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Maxoo Voir le message
    Je suis pas un pro du bash, mais j'ai exécuté ton code et ça ne marchait pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/bash
     
    chemin=/etc/tinydns/root/zone
     
    old="$IFS"
    IFS=/
    set "$chemin"
    IFS="$old"
     
    for i in $*
    do
        echo $i
    done
    renvoie cela chez moi :


    Alors que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/bash
     
    chemin=/etc/tinydns/root/zone
     
    old="$IFS"
    IFS=/
    set "$chemin"
     
    for i in $*
    do
        echo $i
    done
    IFS="$old"
    renvoie :


    Je ne sais pas trop l'expliquer, comme je te dis, je ne suis pas un pro
    Du coup je pensais que tu t'étais trompé, mais si tu dis que non c'est bizarre.
    Citation Envoyé par cristobal78 Voir le message
    j'ai fait l'essai et trouve comme maxoo.
    a+
    Je suis de retour avec un peu de retard. Etant sûr de moi mais néanmoins étonné d'être contredit ... j'ai lancé mon petit Linux pour tester.

    En effet, ton script ainsi présenté fonctionne tel qu'il est décrit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/bin/bash
    chemin=/etc/tinydns/root/zone
     
    old="$IFS"
    IFS=/
    set "$chemin"
     
    for i in $*
    do
        echo $i
    done
    IFS="$old"
    Et le mien ne fonctionne pas comme je le voudrais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/bin/bash
    chemin=/etc/tinydns/root/zone
     
    old="$IFS"
    IFS=/
    set "$chemin"
    IFS="$old"
     
    for i in $*
    do
        echo $i
    done
    Le problème c'est que je sais comment fonctionne le set et l'IFS et donc ça doit forcément venir de par là.
    Tout à coup, pris d'un réflexe, j'enlève les guillemets au set
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/bin/bash
    chemin=/etc/tinydns/root/zone
     
    old="$IFS"
    IFS=/
    set $chemin
    IFS="$old"
     
    for i in $*
    do
        echo $i
    done
    Et là, ça fonctionne parfaitement

    Explications: l'IFS n'est pas utilisé que pour le set. En fait, partout où le shell a besoin de séparer des éléments, il les séparera selon le ou les caractères de l'IFS. Ainsi, quand le for a besoin de traiter des éléments, ils seront traités eux-aussi selon l'IFS. Et malheureusement le fait que les éléments soient affichés séparément n'est qu'un travail du for et non du set.
    A la limite, en écrivant dans ton script "for i in /etc/tinydns/root/zone" ça fonctionnera pareil.

    Toutefois, dans nos scripts initiaux, le fait de mettre des guillemets est un impératif pour indiquer de ne pas séparer les choses (ce qui a rendu mon premier script inefficace)

    Comment rendre ce fait visuellement constatable ? Tout simplement en affichant le nombre de paramètres "$#" juste avant le for. Avec ton script, cela donne "1" vu que dans le tien aussi il y a des guillemets au "set" et que le boulot n'a pas été fait.
    Et avec mon script rectifié, cela donne bien "5" montrant ainsi que le set a bien découpé son argument comme il faut. Et bien entendu, une fois que le set a tout découpé, il est inutile (voire dangereux) de laisser l'IFS dans cet état foireux d'où la remise immédiate dans son état d'origine.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Membre émérite

    Homme Profil pro
    Expert PHP
    Inscrit en
    Novembre 2004
    Messages
    2 127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Expert PHP
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 127
    Points : 2 557
    Points
    2 557
    Par défaut
    Bon ça m'embête un peu de te dire ça, tu avais l'air si content

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    #!/bin/bash
    chemin="chemin 1|chemin 2 chemin 2 et demi|chemin 3"
    echo "\$chemin=\""$chemin"\""
     
    echo "1er TEST :"
    old="$IFS"
    IFS="|"
    set $chemin
    echo "\$#="$#
    IFS="$old"
     
    count=1
    for i in $*
    do
            echo $count" -> "$i
            ((count++))
    done
     
    echo "2eme TEST :"
    old="$IFS"
    IFS="|"
    set $chemin
    echo "\$#="$#
     
    count=1
    for i in $*
    do
            echo $count" -> "$i
            ((count++))
    done
    IFS="$old"
    Si on exécute ce code là. On récupère :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    $chemin="chemin 1|chemin 2 chemin 2 et demi|chemin 3"
    1er TEST :
    $#=3
    1 -> chemin
    2 -> 1
    3 -> chemin
    4 -> 2
    5 -> chemin
    6 -> 2
    7 -> et
    8 -> demi
    9 -> chemin
    10 -> 3
    
    2eme TEST :
    $#=3
    1 -> chemin 1
    2 -> chemin 2 chemin 2 et demi
    3 -> chemin 3
    Du coup en remettant le IFS trop tôt à sa valeur par défaut, on redonne du pouvoir au FOR pour casse en espace en plus de ce qu'il a déjà.

    Du coup, je préfère remettre l'IFS en fin de boucle.

    A moins que tu puisses m'expliquer ou est mon erreur ??

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 720
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 720
    Points : 31 037
    Points
    31 037
    Billets dans le blog
    1
    Par défaut
    Diantre... ton kung-fu serait-il donc meilleur que le mien ? Cela se peut-il ?
    Comme l'oiseau qui voit ses petits tombés du nid se faire écraser par les pattes de l'éléphant, le fantôme de l'échec apparait maintenant devant mes yeux pour venir se rire de moi.
    ...
    ...

    Non ! Faut pas pleurer T'es le plus fort Il faut serrer Les poings très fort

    Tu n'as commis aucune erreur dans ton raisonnement. Effectivement, le set a fonctionné (echo $# le montre et à la limite un echo $1 le montrera encore mieux) mais effectivement ce con de "for" n'a rien panné à ce qu'on veut de lui et a tout re-découpé à sa sauce IFS.

    Sincèrement j'ai failli abandonner. Après-tout, ton raisonnement étant parfait, il n'y avait plus rien à faire et voyais que t'avais réussi à mettre en évidence un cas particulier qui fait foirer le programme là où on s'y attend pas (le bug parfait quoi)
    Mais je me suis souvenu d'une variable dont je ne m'expliquais pas l'utilité jusqu'à ce jour => $@
    Cette variable contient les arguments (comme $*) mais chaque argument est géré comme une chaine => au lieu de contenir $1 $2 $3 ... $n, cette variable contient "$1" "$2" "$3" ... "$n". Subtile différence...

    J'ai donc tenté mais ça n'a pas marché. Puis j'ai tenté et là, WIN. Et ce, avec le IFS bien évidemment repositionné avant la boucle.

    Toutefois la victoire a un gout un peu amer car on ne peut pas nier que t'as quand-même mis en évidence une faille dans ma façon de faire habituelle. Et le fait que j'ai réussi à trouver une solution à ce problème n'empêche pas que j'ai tout un passé de scripts parmi lesquels cette faille peut s'y trouver et ça j'aime pas. Cependant, grâce à toi j'ai aussi compris l'utilité de cette "$@".

    Au fait, pourquoi mon premier for i in $@ (sans guillemets) ne fonctionne pas ? Ben j'en sais trop rien.

    [edit]Si on met "for i" tout court, le script fonctionne aussi. Le "for i" se comporte comme s'il y avait un "in "$@"" par défaut. A retenir...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Membre émérite

    Homme Profil pro
    Expert PHP
    Inscrit en
    Novembre 2004
    Messages
    2 127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Expert PHP
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 127
    Points : 2 557
    Points
    2 557
    Par défaut
    Pour le "for i" : je dis qu'il vaut mieux se méfier des comportements par défaut. Ca peut changer d'une machine à une autre.

    Du coup Lundi je testerai ta méthode, et si $@ existe, c'est pas pour rien à mon avis !!

    Du coup ça résoudrait d'autre problème que j'avais, donc pas mal.

  11. #11
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Points : 2 505
    Points
    2 505
    Par défaut
    Si tu veux récupérer un tableau, tu peux faire simplement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IFS=/ array=( $chemin )
    Et tu récupère les composantes du chemin dans ${array[1]}, ${array[2]}, etc (${array[0]} sera vide puisque c'est ce qui se trouve avant le premier slash).

  12. #12
    Membre émérite

    Homme Profil pro
    Expert PHP
    Inscrit en
    Novembre 2004
    Messages
    2 127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Expert PHP
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 127
    Points : 2 557
    Points
    2 557
    Par défaut
    Nickel, d'ailleurs je préfère passer par un tableau. Après c'est plus simple, y a pas d'autre redécoupage.

    Du coup pour ceux qui ont la flemme de lire tout le topic : Voici deux manière de faire un explode en bash.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    #!/bin/bash
    chemin="chemin 1|chemin 2 chemin 2 et demi|chemin 3"
    echo "\$chemin=\""$chemin"\""
     
    echo "FOR"
    old="$IFS"
    IFS="|"
    set $chemin
    IFS="$old"
    echo "\$#="$#
     
    count=1
    for i in "$@"
    do
            echo $count" -> "$i
            ((count++))
    done
     
    echo "TABLEAU"
    old="$IFS"
    IFS="|"
    tab=( $chemin )
    IFS="$old"
     
    for (( i=0 ; i<${#tab[*]} ; i++ )) ; do
            echo $i" -> "${tab[$i]}
    done
    Edit : Est-ce qu'il y a une FAQ BASH pour le mettre dedans ?

Discussions similaires

  1. aide pour une fonction collision en bash
    Par dipper dans le forum Linux
    Réponses: 5
    Dernier message: 14/04/2011, 23h21
  2. Explode en bash dans un tableau
    Par Maillon dans le forum Linux
    Réponses: 6
    Dernier message: 18/11/2008, 08h18
  3. equivalent fonction explode (php)
    Par lololoic dans le forum Access
    Réponses: 6
    Dernier message: 21/08/2006, 18h34
  4. equivalent de la fonction EXPLODE de php
    Par gyouk dans le forum ASP
    Réponses: 1
    Dernier message: 28/11/2005, 10h49
  5. Equivalent de la fonction trim
    Par PCHINK dans le forum C
    Réponses: 6
    Dernier message: 21/03/2004, 18h02

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