Précédent   Forum des professionnels en informatique > Systèmes > Autres systèmes > Unix
Unix Forum d'entraide sur les systèmes Unix et dérivés (*BSD, AIX, etc.). Avant de poster ->F.A.Q BSD F.A.Q. Aix
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 29/06/2011, 15h58   #1
Membre régulier
 
Inscription : juin 2002
Messages : 114
Détails du profil
Informations personnelles :
Âge : 26

Informations forums :
Inscription : juin 2002
Messages : 114
Points : 77
Points : 77
Envoyer un message via MSN à Odulo
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 :

Citation:
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 :

Citation:
$ 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 :
Citation:
*.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 :
Citation:
# 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
Odulo est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 30/06/2011, 14h24   #2
Membre émérite
 
Avatar de Pouic
 
Inscription : octobre 2004
Messages : 668
Détails du profil
Informations personnelles :
Âge : 28
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : octobre 2004
Messages : 668
Points : 904
Points : 904
Code :
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.)
__________________
Software becomes slower faster than hardware becomes faster

http://xrenault.developpez.com
API C standard (C ANSI )
Pouic est déconnecté   Envoyer un message privé Réponse avec citation 40
Vieux 30/06/2011, 14h49   #3
Membre régulier
 
Inscription : juin 2002
Messages : 114
Détails du profil
Informations personnelles :
Âge : 26

Informations forums :
Inscription : juin 2002
Messages : 114
Points : 77
Points : 77
Envoyer un message via MSN à Odulo
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
Citation:
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 !
Odulo est déconnecté   Envoyer un message privé Réponse avec citation 01
Vieux 30/06/2011, 14h54   #4
Membre émérite
 
Avatar de Pouic
 
Inscription : octobre 2004
Messages : 668
Détails du profil
Informations personnelles :
Âge : 28
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : octobre 2004
Messages : 668
Points : 904
Points : 904
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
__________________
Software becomes slower faster than hardware becomes faster

http://xrenault.developpez.com
API C standard (C ANSI )
Pouic est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 30/06/2011, 16h13   #5
Membre régulier
 
Inscription : juin 2002
Messages : 114
Détails du profil
Informations personnelles :
Âge : 26

Informations forums :
Inscription : juin 2002
Messages : 114
Points : 77
Points : 77
Envoyer un message via MSN à Odulo
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.
Odulo est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 30/06/2011, 16h22   #6
Membre émérite
 
Avatar de Pouic
 
Inscription : octobre 2004
Messages : 668
Détails du profil
Informations personnelles :
Âge : 28
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : octobre 2004
Messages : 668
Points : 904
Points : 904
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 :
1
2
3
4
5
6
pushd $patchdir
for i in [...]
<...>
done;
popd
__________________
Software becomes slower faster than hardware becomes faster

http://xrenault.developpez.com
API C standard (C ANSI )
Pouic est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 01/07/2011, 10h48   #7
Membre régulier
 
Inscription : juin 2002
Messages : 114
Détails du profil
Informations personnelles :
Âge : 26

Informations forums :
Inscription : juin 2002
Messages : 114
Points : 77
Points : 77
Envoyer un message via MSN à Odulo
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 !
Odulo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/07/2011, 13h13   #8
Membre émérite
 
Avatar de Pouic
 
Inscription : octobre 2004
Messages : 668
Détails du profil
Informations personnelles :
Âge : 28
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : octobre 2004
Messages : 668
Points : 904
Points : 904
Disons que tu peux t'en sortir comme ça alors :
Code :
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.
__________________
Software becomes slower faster than hardware becomes faster

http://xrenault.developpez.com
API C standard (C ANSI )
Pouic est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 01/07/2011, 15h18   #9
Membre régulier
 
Inscription : juin 2002
Messages : 114
Détails du profil
Informations personnelles :
Âge : 26

Informations forums :
Inscription : juin 2002
Messages : 114
Points : 77
Points : 77
Envoyer un message via MSN à Odulo
Effectivement ca me plairait bien car ca reste localise mais ce n'est valable que si seul le premier argument a une regex :

Code :
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
Odulo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/07/2011, 17h44   #10
Membre émérite
 
Avatar de Pouic
 
Inscription : octobre 2004
Messages : 668
Détails du profil
Informations personnelles :
Âge : 28
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : octobre 2004
Messages : 668
Points : 904
Points : 904
Alors je te propose un truc comme ça :

Code :
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
__________________
Software becomes slower faster than hardware becomes faster

http://xrenault.developpez.com
API C standard (C ANSI )
Pouic est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 01/07/2011, 18h11   #11
Membre régulier
 
Inscription : juin 2002
Messages : 114
Détails du profil
Informations personnelles :
Âge : 26

Informations forums :
Inscription : juin 2002
Messages : 114
Points : 77
Points : 77
Envoyer un message via MSN à Odulo
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.
Odulo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/07/2011, 10h59   #12
Membre émérite
 
Avatar de Pouic
 
Inscription : octobre 2004
Messages : 668
Détails du profil
Informations personnelles :
Âge : 28
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : octobre 2004
Messages : 668
Points : 904
Points : 904
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 :
sh script.sh *.patch my_archive *.toto *.patch
Tu fais
Code :
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 $@
__________________
Software becomes slower faster than hardware becomes faster

http://xrenault.developpez.com
API C standard (C ANSI )
Pouic est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 04/07/2011, 16h56   #13
Membre régulier
 
Inscription : juin 2002
Messages : 114
Détails du profil
Informations personnelles :
Âge : 26

Informations forums :
Inscription : juin 2002
Messages : 114
Points : 77
Points : 77
Envoyer un message via MSN à Odulo
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 !
Odulo est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 02h41.


 
 
 
 
Partenaires

Hébergement Web