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

Unix Discussion :

[Bash] Ne pas interpreter une regex lors d'une boucle for


Sujet :

Unix

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    115
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 115
    Points : 104
    Points
    104
    Par défaut [Bash] Ne pas interpreter une regex lors d'une boucle for
    Bonjour,

    Voila je vous expose mon petit soucis. J'ai un script qui peut recevoir un nombre d'arguments variables, les deux premiers (obligatoires) sont des repertoires et les suivants sont des patches a appliquer.

    Ces arguments peuvent etre de differents types : un repertoire, une archive ou meme un regex du type *.patch.

    Au depart je faisais quelque chose du genre :

    builddir=${1}
    patchdir=${2}
    shift 2
    patchlist=${@}

    for i in $patchlist ; do
    ...
    done
    Le soucis c'est que lorsque ma boucle arrive a une regex du type *.patch, la regex est interpretee. Un exemple sera plus clair qu'une explication :

    $ mkdir test_bash
    $ cd test_bash/
    $ touch toto1.patch
    $ touch toto2.patch
    $ for i in "*.patch my_archive.tar.bz2" ; do echo $i ; done
    toto1.patch toto2.patch my_archive.tar.bz2
    Je voudrais avoir :
    *.patch my_archive.tar.bz2
    Est-ce que vous voyez une solution pas trop tordue ? Une solution serait peut-etre de mettre un caractere d'echappement avant l'etoile mais je ne peux pas presumer de la regex qu'on me donnera.

    En attendant j'ai trouve une solution mais elle ne me plait guere :
    # go to the patch directory because $patchlist is interpreted when doing
    # for i in $patchlist
    pushd ${patchdir}
    index=0
    for i in $patchlist ; do
    patchlist_interpreted[${index}]="$i"
    index=`expr ${index} + 1`
    echo patchlist_interpreted[${index}]=$i
    done
    popd

    for index in "${!patchlist_interpreted[@]}" ; do
    ...
    Merci

    Ludovic

  2. #2
    Membre éprouvé
    Avatar de Pouic
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    669
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 669
    Points : 977
    Points
    977
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    TOTO="*.patch my_archive"
     
    set -f
    for i in $TOTO; do
    echo $i;
    done
    set +f
    set -f désactive l'expansion des "wildcards" (asterixes, etc.)

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    115
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 115
    Points : 104
    Points
    104
    Par défaut
    Merci pour cette astuce.

    Il va falloir que je teste si cela fonctionne bien car dans l'exemple que tu me donnes, tu reactives l'expansion des wilcards en sortie de boucle mais je vais en avoir besoin a l'interieur.

    Du coup pour etre tranquille, je peux faire quelque chose du genre :

    set -f
    for i in $TOTO ; do
    if
    ...
    else
    set +f
    ...
    set -f
    fi
    done
    Si je dois faire comme ca j'avoue que ca me plait un peu moins.

    En tout cas merci pour cette reponse ca me resservira a coup sur !

  4. #4
    Membre éprouvé
    Avatar de Pouic
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    669
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 669
    Points : 977
    Points
    977
    Par défaut
    Citation Envoyé par Odulo Voir le message
    Merci pour cette astuce.

    Il va falloir que je teste si cela fonctionne bien car dans l'exemple que tu me donnes, tu reactives l'expansion des wilcards en sortie de boucle mais je vais en avoir besoin a l'interieur.

    <...>

    Si je dois faire comme ca j'avoue que ca me plait un peu moins.
    Ben oui, mais de toute façon, si selon les cas tu veux ou ne veux pas activer les wildcards, il faudra bien que tu le dises à bash
    Alors que ce soit avec un set -f ou autre chose, tu n'y couperas pas, ton code ne peux pas deviner pour toi quand tu as besoin ou non des wildcards

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    115
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 115
    Points : 104
    Points
    104
    Par défaut
    Oui je suis d'accord, c'est juste dans le sens que desactiver les wildchars et les reactiver a un endroit ca me va mais commencer a le faire plusieurs fois dans le code j'aime moins, ca devient moins lisible.

    Du coup je me pose la question utiliser set -f / set +f plusieurs fois dans le code ou rester sur la soution que j'avais deja utilisee c'est a dire me placer au bon endroit pour que lorsque la regex est interpretee elle le soit correctement.

    L'explication n'est peut-etre pas tres claire, je recois donc un argument avec le chemin des patches et une liste de patches a utiliser dans ce repertoire.
    Mon soucis etait que lors de l'interpretation dans la boucle for, bash prenait donc les fichiers qui pouvaient correspondre a la regex depuis l'endroit ou est execute le script et non depuis le repertoire des patches.
    Du coup j'allais dans ce repertoire, je recuperais un tableau avec tous les fichiers correspondant a la regex, je retournais dans mon repertoire d'origine et je continuais avec mon tableau.

    Je ne trouvais pas ca hyper propre ni clair mais je n'ai pas eu de retour negatif. Du coup je me pose la question garder ces quelques lignes ou utiliser set -f.

  6. #6
    Membre éprouvé
    Avatar de Pouic
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    669
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 669
    Points : 977
    Points
    977
    Par défaut
    Citation Envoyé par Odulo Voir le message
    Oui je suis d'accord, c'est juste dans le sens que desactiver les wildchars et les reactiver a un endroit ca me va mais commencer a le faire plusieurs fois dans le code j'aime moins, ca devient moins lisible.

    Du coup je me pose la question utiliser set -f / set +f plusieurs fois dans le code ou rester sur la soution que j'avais deja utilisee c'est a dire me placer au bon endroit pour que lorsque la regex est interpretee elle le soit correctement.

    L'explication n'est peut-etre pas tres claire, je recois donc un argument avec le chemin des patches et une liste de patches a utiliser dans ce repertoire.
    Mon soucis etait que lors de l'interpretation dans la boucle for, bash prenait donc les fichiers qui pouvaient correspondre a la regex depuis l'endroit ou est execute le script et non depuis le repertoire des patches.
    Du coup j'allais dans ce repertoire, je recuperais un tableau avec tous les fichiers correspondant a la regex, je retournais dans mon repertoire d'origine et je continuais avec mon tableau.

    Je ne trouvais pas ca hyper propre ni clair mais je n'ai pas eu de retour negatif. Du coup je me pose la question garder ces quelques lignes ou utiliser set -f.
    Pourquoi ne pas aller dans le répertoire des patchs pour éviter le problème ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    pushd $patchdir
    for i in [...]
    <...>
    done;
    popd

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    115
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 115
    Points : 104
    Points
    104
    Par défaut
    En fait c'est exactement ce que je vais mais juste pour recuperer ma liste "interpretee" avant de faire ma boucle.

    Je ne le fais pas pour ma boucle for elle-meme car pour moi c'est plus simple de rester a la racine du projet plutot que de changer de repertoire plusieurs fois a l'interieur.

    Je trouvais ca un peu "tricky" mais ca ne semble pas choquer donc ca va. J'esperais qu'il existe une solution juste pour la ligne de mon for un truc du style

    et \$args aurait permis de ne pas interpreter ma regex par exemple !

  8. #8
    Membre éprouvé
    Avatar de Pouic
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    669
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 669
    Points : 977
    Points
    977
    Par défaut
    Disons que tu peux t'en sortir comme ça alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    #!/bin/bash                                                                                                                                                                                                                                   
     
    TOTO="*.patch my_archive"
     
    set -f
    for i in $TOTO; do
    set +f
    echo "not expanded" "$i";
    echo "expanded" $i;
    done
    Tu repositionnes l'extension de variables juste après le for. Du coup, dans tes éléments de boucle for ne sont pas expansés.

    Et ensuite, si tu as besoin d'interpréter les wildcards contenus dans la variable i, tu utilises $i, et sinon, si tu ne veux pas que ce soit interprété, tu utilises "$i" (avec les guillemets).

    Je ne sais pas si ça te convient davantage.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    115
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 115
    Points : 104
    Points
    104
    Par défaut
    Effectivement ca me plairait bien car ca reste localise mais ce n'est valable que si seul le premier argument a une regex :

    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
     
    $ cat my_script.sh 
    #!/bin/bash
     
    my_args=$@
     
    set -f
    for i in $@; do
            set +f
            echo "not expanded:" "$i";
            echo "expanded:" $i;
    done;
    $ ./my_script.sh test *.patch my_archive.tar.bz2
    not expanded: test
    expanded: test
    not expanded: toto1.patch
    expanded: toto1.patch
    not expanded: toto2.patch
    expanded: toto2.patch
    not expanded: my_archive.tar.bz2
    expanded: my_archive.tar.bz2

  10. #10
    Membre éprouvé
    Avatar de Pouic
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    669
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 669
    Points : 977
    Points
    977
    Par défaut
    Alors je te propose un truc comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/bin/bash                                                                                                                                                                                                                                  
     
    TOTO="*.patch my_archive *.toto *.patch"
     
    set -f
    a=($TOTO)
    set +f
     
    for i in "${a[@]}"; do
    echo "not expanded" "$i"
    echo "expanded" $i
    done
    Tu passes par un tableau où tu n'interprêtes pas les éléments.
    Puis parcours du tableau où tu interprètes (ou non) les wildcards avec ou sans les guillemets autour de $i.

    Après faut faire gaffe, si tu passes par $@, ça risque de t'interpréter les wildcards sans même te demander ton avis

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    115
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 115
    Points : 104
    Points
    104
    Par défaut
    Citation Envoyé par Pouic Voir le message
    Après faut faire gaffe, si tu passes par $@, ça risque de t'interpréter les wildcards sans même te demander ton avis
    Malheureusement c'est ce qui se passe mais j'adore ta solution sinon : un commentaire, 3 lignes et c'est fait.

  12. #12
    Membre éprouvé
    Avatar de Pouic
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    669
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 669
    Points : 977
    Points
    977
    Par défaut
    Citation Envoyé par Odulo Voir le message
    Malheureusement c'est ce qui se passe mais j'adore ta solution sinon : un commentaire, 3 lignes et c'est fait.
    Dernière chose que tu puisses faire dans ce cas : lors de l'appel de ton script, au lieu de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sh script.sh *.patch my_archive *.toto *.patch
    Tu fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    sh script.sh "*.patch my_archive *.toto *.patch"
    et tu peux alors reprendre le code que je t'ai proposé en remplaçant $TOTO par $@

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    115
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 115
    Points : 104
    Points
    104
    Par défaut
    Ok, je ne me souviens plus comment est fait l'appel, il faudra que je regarde a nouveau le code mais je pense que ce sera bon et que ce sera la solution adoptee.

    Merci bien pour cette aide tres efficace !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Ne pas changer d'onglet lors d'une redirection de page sur un billet
    Par lolef dans le forum Développement Sharepoint
    Réponses: 1
    Dernier message: 12/08/2011, 11h24
  2. Pourquoi ai-je une erreur lors d'une recherche si la valeur n'existe pas ?
    Par blackndoor dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 17/03/2009, 11h22
  3. copie d'une table Y d'une base A vers une table X d'une base
    Par moneyboss dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 30/08/2005, 21h24
  4. Réponses: 2
    Dernier message: 21/06/2004, 15h55

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