OVH Cloud OVH Cloud

Expansion de variable en bash

11 réponses
Avatar
Arnaud Launay
Hop,

J'ai un petit soucis en bash:

for subdir in imap/{,db,log} ; do
mkdir $subdir
done

marche impec, mais:

SUB="imap/{,db,log}"
for subdir in ${SUB}; do
mkdir $subdir
done

Me crée un répertoire "{,db,log}" ....

Visiblement, je rate quelque chose, mais quoi ?!?

Arnaud.
--
Perso: http://launay.org/blog/
Consulting: http://www.cusae.com/
Hébergement: http://www.nocworld.com/

10 réponses

1 2
Avatar
DINH Viêt Hoà

SUB="imap/{,db,log}"
for subdir in ${SUB}; do
mkdir $subdir
done

Me crée un répertoire "{,db,log}" ....


1. ${SUB} est un objet argument unique, 'for' prend une liste
d'arguments

par exemple :
SUB="a b c d"
for i in $SUB; do
echo un argument
echo $SUB
done

qui t'affichera :
un argument
a b c d

par rapport à :
for i in a b c d ; do
echo un argument
echo $SUB
done

qui t'affichera :
un argument
a
un argument
b
un argument
c
un argument
d

2. "imap/{,db,log}" entre " n'est pas évalué, seuls les éventuelles
références à des variables sont évaluées entre les
double-guillemets.

par exemple :
SUB="imap/{,db,log}"
echo $SUB

resultat :
imap/{,db,log}

toto=titi
SUB="imap/$toto"
echo $SUB

résultat :
imap/titi


Pour ce que tu voulais faire :

SUB="imap/{,db,log}"
for subdir in `eval echo ${SUB}`; do
mkdir $subdir
done

'eval' apparemment est spécifique bash. Si Stéphane Chazelas a une
variante POSIX, ce serait intéressant.

--
DINH V. Hoa,

"un esprit sain dans un corps sain" -- voisin

Avatar
Nicolas George
DINH Viêt Hoà wrote in message :
par exemple :
SUB="a b c d"
for i in $SUB; do
echo un argument
echo $SUB
done

qui t'affichera :
un argument
a b c d

par rapport à :
for i in a b c d ; do
echo un argument
echo $SUB
done

qui t'affichera :
un argument
a
un argument
b
un argument
c
un argument
d


Ce serait bien de tester ses exemples : ça évite de dire exactement le
contraire de la réalité. En sh/bash (mais pas en zsh), « $SUB » est découpé
en mots (suivant l'IFS) lors de l'expansion. Si on veut qu'il soit gardé en
un seul mot, on doit écrire « "$SUB" ». Comparer :

T="a b c d"
for i in $T; do echo $i; done
for i in "$T"; do echo $i; done

2. "imap/{,db,log}" entre " n'est pas évalué, seuls les éventuelles
références à des variables sont évaluées entre les
double-guillemets.


Ça, c'est la bonne raison. Mais en fait, « imap/{,db,log} » n'est pas évalié
dans le contexte d'une affectation, double guillemets ou pas.

Personnellement, pour résoudre ça, j'utiliserais zsh, et j'écrirais
« SUB=(imap/{,db,log}) », qui marche parfaitement.

Avatar
Arnaud Launay
Le Sat, 22 Oct 2005 12:15:01 +0000 (UTC), Nicolas George écrivit:
Personnellement, pour résoudre ça, j'utiliserais zsh, et j'écrirais
« SUB=(imap/{,db,log}) », qui marche parfaitement.


A part que c'est dans le cadre d'un ebuild pour la Gentoo, donc
ça ne sera pas possible... (et dans la version réelle, il n'y a
pas que deux sous-répertoires, donc je vais éviter de les
lister). Va falloir trouver autre chose...

Arnaud.
--
Perso: http://launay.org/blog/
Consulting: http://www.cusae.com/
Hébergement: http://www.nocworld.com/

Avatar
Christophe Gaubert
Pour ce que tu voulais faire :

SUB="imap/{,db,log}"
for subdir in `eval echo ${SUB}`; do
mkdir $subdir
done

'eval' apparemment est spécifique bash. Si Stéphane Chazelas a une
variante POSIX, ce serait intéressant.



En même temps, il suffit de faire quelque chose comme :
SUB="db log"
for subdir in $SUB ; do
mkdir imap/$subdir
done
Avec la possibilité de mettre "imap" dans une variable aussi.


--
Christophe Gaubert
http://perso.wanadoo.fr/christophe.gaubert
Mail posté depuis un système libre GNU/Linux

Avatar
Arnaud Launay
Le Sat, 22 Oct 2005 15:15:27 +0200, Christophe Gaubert écrivit:
'eval' apparemment est spécifique bash. Si Stéphane Chazelas
a une variante POSIX, ce serait intéressant.
En même temps, il suffit de faire quelque chose comme :

SUB="db log"
for subdir in $SUB ; do
mkdir imap/$subdir
done
Avec la possibilité de mettre "imap" dans une variable aussi.


J'y avais évidemment pensé, mais je préférerais garder le code un
tant soit peu factorisé. Sinon, tant que j'y suis, je peux aussi
tout mettre en long, et sans boucle, hein.

Mais n'empêche que s'il existe une solution simple, ça m'intéresse..

Arnaud.
--
Perso: http://launay.org/blog/
Consulting: http://www.cusae.com/
Hébergement: http://www.nocworld.com/


Avatar
Christophe Gaubert
J'y avais évidemment pensé, mais je préférerais garder le code un
tant soit peu factorisé. Sinon, tant que j'y suis, je peux aussi
tout mettre en long, et sans boucle, hein.


Je ne vois pas en quoi ma version est moins factorisée que ce que tu
tentes de faire ?
SUB a plus ou moins la même valeur. Et l'évaluation ménerait au même "for".
Non ?

--
Christophe Gaubert
http://perso.wanadoo.fr/christophe.gaubert
Mail posté depuis un système libre GNU/Linux

Avatar
Cem
Le 22-10-2005, DINH Viêt Hoà a écrit :

SUB="imap/{,db,log}"
for subdir in ${SUB}; do
mkdir $subdir
done

Me crée un répertoire "{,db,log}" ....


Pour ce que tu voulais faire :

SUB="imap/{,db,log}"
for subdir in `eval echo ${SUB}`; do
mkdir $subdir
done

'eval' apparemment est spécifique bash. Si Stéphane Chazelas a une
variante POSIX, ce serait intéressant.

D'après ce que dit le manuel de bash, eval est une commande conforme au

standard POSIX 1003.2 et n'a rien de "specifique bash".
http://www.gnu.org/software/bash/manual/bashref.html#SEC56


Avatar
DINH Viêt Hoà

'eval' apparemment est spécifique bash. Si Stéphane Chazelas a une
variante POSIX, ce serait intéressant.

D'après ce que dit le manuel de bash, eval est une commande conforme au

standard POSIX 1003.2 et n'a rien de "specifique bash".
http://www.gnu.org/software/bash/manual/bashref.html#SEC56


effectivement.
http://www.opengroup.org/onlinepubs/009695399/utilities/eval.html

--
DINH V. Hoa,

"un esprit sain dans un corps sain" -- voisin


Avatar
Xavier Gachon
Le 22-10-2005, Christophe Gaubert a écrit :
SUB a plus ou moins la même valeur. Et l'évaluation ménerait au même "for".
Non ?


Il me semble qu'il voudrait isoler entierement ce sur quoi le for
s'applique de la boucle elle meme, ce qui est plutot une bonne chose.

Mais je crois que personne n'a jusqu'ici remarqué que la raison la
plus simple pour laquelle cela ne peut fonctionner est tout simplement
qu'avec bash les braces expansions (qui ne sont pas POSIX :) ont lieu
avant les paremeters expansions d'ou la necessité deja decrite meme si
mal argumentée de passer par eval si l'on place une brace expansion
a l'interieur d'une variable, ou encore de forcer les braces expansions
avant l'affectation a la variable ce qui est sans doute le plus simple,
exemple:

SUB="$(echo a{b,c})"
for i in $SUB; do echo $i; done

ou s'il veut absolument maintenir la variable sans code associé
a l'expansion, separer cette derniere, via une autre variable (ou
l'argument passé a for comme cela a deja ete montré) :

SUB="a{b,c}"
BRACE_EXPANDED_SUB="$(eval echo $SUB)"
for i in $BRACE_EXPANDED_SUB; do echo $i; done

hope this help, xavier.

Avatar
Arnaud Launay
Le Sun, 23 Oct 2005 00:46:44 +0000 (UTC), Xavier Gachon écrivit:
SUB="$(echo a{b,c})"
for i in $SUB; do echo $i; done


Je prends ça, ça me convient très bien. Merci !

Arnaud.
--
Perso: http://launay.org/blog/
Consulting: http://www.cusae.com/
Hébergement: http://www.nocworld.com/

1 2