OVH Cloud OVH Cloud

evaluation indirecte de paramètre en shell portable

22 réponses
Avatar
rixed
Coucou la liste.

Je suppose que c'est une FAQ, mais je n'ai pas réussit à mettre la main
sur la FAQ du groupe.

Donc, question :

Sous zsh, on peut faire :

$ toto="valeur de toto"
$ titi=toto
$ echo ${(P)titi}
valeur de toto
$ youpi
command not found: youpi

J'aimerai savoir s'il n'y a pas moyen de faire cela en shell portable.
Genre quelquechose qui fonctionnerait aussi bien avec bash, zsh, tcsh...
Et pourquoi pas aussi en shell POSIX.

10 réponses

1 2 3
Avatar
Stephane Chazelas
On Tue, 28 Feb 2006 18:14:12 +0100, Pascal Bourguignon wrote:
Stephane Chazelas writes:
Note que ca ne fait pas de sens d'ecrire du code qui marche a la
fois en shell bourne-like et en csh-like, ce sont deux familles
completement incompatibles.


Pas tant que ça:

------(happy.source)----------------------------------------------------
cat /*dev/null; echo "Happy New Year"!
cat <<c*/ /*dev/null | cat > /dev/null
[...]


Ou http://stchaz.free.fr/which_interpreter :)

--
Stephane


Avatar
rixed
On 2006-02-28, Pascal Bourguignon wrote:
writes:
man bash


Qu'est-ce qui te fait croire que je ne l'ai pas lu ?


Tu aurais trouvé tout seul eval et ${!toto}.


${!toto}, d'une part j'ai été trop bète pour le faire marcher
(je backslashais le !, trop habitué à zsh), et d'autre part ca
ne m'allait pas, car en fait dans mon cas la variable 'toto' ne
contient que la partie variable du nom d'une autre variable
(c'est DEFFILE_MIME ou DEFFILE_NODE, toto valant "MIME" ou "NODE").

Mais eval fonctionne parfaitement. Je ne l'ai pas vu dans la page
de manuel car il n'y est pas fait référence dans le chapitre sur
les parameters expansions (amis francophones bonsoir).



Avatar
Pascal Bourguignon
rixed writes:

On 2006-02-28, Pascal Bourguignon wrote:
writes:
man bash


Qu'est-ce qui te fait croire que je ne l'ai pas lu ?


Tu aurais trouvé tout seul eval et ${!toto}.


${!toto}, d'une part j'ai été trop bète pour le faire marcher
(je backslashais le !, trop habitué à zsh), et d'autre part ca
ne m'allait pas, car en fait dans mon cas la variable 'toto' ne
contient que la partie variable du nom d'une autre variable
(c'est DEFFILE_MIME ou DEFFILE_NODE, toto valant "MIME" ou "NODE").


for toto in MIME NODE ; do
titiÞFFILE_$toto
echo ${!titi}
done

Mais eval fonctionne parfaitement. Je ne l'ai pas vu dans la page
de manuel car il n'y est pas fait référence dans le chapitre sur
les parameters expansions (amis francophones bonsoir).



--
__Pascal Bourguignon__ http://www.informatimago.com/




Avatar
Stephane Chazelas
2006-03-01, 00:46(+01), Pascal Bourguignon:
rixed writes:

On 2006-02-28, Pascal Bourguignon wrote:
writes:
man bash


Qu'est-ce qui te fait croire que je ne l'ai pas lu ?


Tu aurais trouvé tout seul eval et ${!toto}.


${!toto}, d'une part j'ai été trop bète pour le faire marcher
(je backslashais le !, trop habitué à zsh), et d'autre part ca
ne m'allait pas, car en fait dans mon cas la variable 'toto' ne
contient que la partie variable du nom d'une autre variable
(c'est DEFFILE_MIME ou DEFFILE_NODE, toto valant "MIME" ou "NODE").


for toto in MIME NODE ; do
titiÞFFILE_$toto
echo ${!titi}
done
[...]


Note l'objet de l'enfilade. (le subject du thread)

${!...} n'est pas standard. C'est ksh93/bash specific, ca ne
marche meme pas pareil dans ces deux shells (pour les arrays par
exemple).

--
Stéphane





Avatar
Pascal Bourguignon
Stephane Chazelas writes:

2006-03-01, 00:46(+01), Pascal Bourguignon:
rixed writes:

On 2006-02-28, Pascal Bourguignon wrote:
writes:
man bash


Qu'est-ce qui te fait croire que je ne l'ai pas lu ?


Tu aurais trouvé tout seul eval et ${!toto}.


${!toto}, d'une part j'ai été trop bète pour le faire marcher
(je backslashais le !, trop habitué à zsh), et d'autre part ca
ne m'allait pas, car en fait dans mon cas la variable 'toto' ne
contient que la partie variable du nom d'une autre variable
(c'est DEFFILE_MIME ou DEFFILE_NODE, toto valant "MIME" ou "NODE").


for toto in MIME NODE ; do
titiÞFFILE_$toto
echo ${!titi}
done
[...]


Note l'objet de l'enfilade. (le subject du thread)

${!...} n'est pas standard. C'est ksh93/bash specific, ca ne
marche meme pas pareil dans ces deux shells (pour les arrays par
exemple).


Non, ce n'est pas standard. Mais ce n'est pas grave:

indirection () {
var="$1"
case "$SHELL" in
*/bash) value="${!var}" ; printf "%s" ${!value} ;;
...) ... ;;
*) printf "Désolé, je ne connais pas ce shell %sn" "$SHELL" ; exit 1 ;;
esac
}

titi«c
toto=titi
printf "toto^ = %sn" $(indirection toto)




Bien sur, si on a beaucoup de choses qui dépendent du shell on factorisera:

case "$SHELL" in
*/bash)
indirection () {
var="$1" ; value="${!var}" ; printf "%s" ${!value}
}
truc () {
...
}
machin () {
...
}
;;
...)
indirection () {
...
}
truc () {
...
}
machin () {
...
}
;;
)
printf "Désolé, je ne connais pas ce shell %sn" "$SHELL"
exit 1
;;
esac


Ainsi, on profite des primitives optimisées de chaque shell, au lieu
d'écrire un code générique, alambiqué, et qui fonctionne mal partout.

--
__Pascal Bourguignon__ http://www.informatimago.com/

"You can tell the Lisp programmers. They have pockets full of punch
cards with close parentheses on them." --> http://tinyurl.com/8ubpf






Avatar
Stephane Chazelas
On Wed, 01 Mar 2006 10:36:27 +0100, Pascal Bourguignon wrote:
[...]
${!...} n'est pas standard. C'est ksh93/bash specific, ca ne
marche meme pas pareil dans ces deux shells (pour les arrays par
exemple).


Non, ce n'est pas standard. Mais ce n'est pas grave:

indirection () {
var="$1"
case "$SHELL" in
*/bash) value="${!var}" ; printf "%s" ${!value} ;;
...) ... ;;
*) printf "Désolé, je ne connais pas ce shell %sn" "$SHELL" ; exit 1 ;;
esac
}
[...]


En quoi verifier $SHELL aide-t-il $SHELL contient le shell
interactif de preference de l'utilisateur (par defaut, son shell
de login), ca n'a rien a voir avec le shell courant (qui
interprete le code courant).

--
Stephane


Avatar
Pascal Bourguignon
Stephane Chazelas writes:

On Wed, 01 Mar 2006 10:36:27 +0100, Pascal Bourguignon wrote:
[...]
${!...} n'est pas standard. C'est ksh93/bash specific, ca ne
marche meme pas pareil dans ces deux shells (pour les arrays par
exemple).


Non, ce n'est pas standard. Mais ce n'est pas grave:

indirection () {
var="$1"
case "$SHELL" in
*/bash) value="${!var}" ; printf "%s" ${!value} ;;
...) ... ;;
*) printf "Désolé, je ne connais pas ce shell %sn" "$SHELL" ; exit 1 ;;
esac
}
[...]


En quoi verifier $SHELL aide-t-il $SHELL contient le shell
interactif de preference de l'utilisateur (par defaut, son shell
de login), ca n'a rien a voir avec le shell courant (qui
interprete le code courant).


Ah. Dans ce cas, il faudrait effectivement tester autre chose. Il
semble que dans le cas de bash, on pourrait peut être tester:

if [ -n "${BASH}" ] ; then
do bash stuff
fi


--
__Pascal Bourguignon__ http://www.informatimago.com/

CONSUMER NOTICE: Because of the "uncertainty principle," it is
impossible for the consumer to simultaneously know both the precise
location and velocity of this product.



Avatar
Stephane Chazelas
On Wed, 01 Mar 2006 12:05:52 +0100, Pascal Bourguignon wrote:
[...]
Ah. Dans ce cas, il faudrait effectivement tester autre chose. Il
semble que dans le cas de bash, on pourrait peut être tester:

if [ -n "${BASH}" ] ; then
do bash stuff
fi
[...]


[ -n "$BASH_VERSION" ]

mais je ne vois pas trop l'interet.

Suffit de mettre un

#! /usr/bin/env bash

en haut du script si on veut utiliser des features specific a
bash.

Par contre, en suite, il faudra sans doute ajouter un:

case $BASH_VERSION in
1.*|2.0.[0-2]*)
echo "you need this or that version" >&2
exit 1;;
[3-9]*|[1-9][0-9]*)
echo "warning: it is not guaranteed to work with that shell.
This script has not been tested with that shell and we use
non-standard features that tend to work differently with
different versions" >&2;;
esac

--
Stephane

Avatar
Pascal Bourguignon
Stephane Chazelas writes:

On Wed, 01 Mar 2006 12:05:52 +0100, Pascal Bourguignon wrote:
[...]
Ah. Dans ce cas, il faudrait effectivement tester autre chose. Il
semble que dans le cas de bash, on pourrait peut être tester:

if [ -n "${BASH}" ] ; then
do bash stuff
fi
[...]


[ -n "$BASH_VERSION" ]

mais je ne vois pas trop l'interet.

Suffit de mettre un

#! /usr/bin/env bash

en haut du script si on veut utiliser des features specific a
bash.


Je suis bien d'accord.
Je trouve bien plus facile de commencer un script par:


wget ftp://ftp.gnu.org/gnu/bash/bash-2.05.tar.bz2
tar jxf bash-2.05.tar.bz2
cd bash-2.05
./configure
make
make install
bash script.bash

que de s'embêter à faire des scripts "portables"...


--
__Pascal Bourguignon__ http://www.informatimago.com/

Nobody can fix the economy. Nobody can be trusted with their finger
on the button. Nobody's perfect. VOTE FOR NOBODY.


Avatar
Jean-Louis Liagre
Pascal Bourguignon wrote:
Stephane Chazelas writes:

On Wed, 01 Mar 2006 12:05:52 +0100, Pascal Bourguignon wrote:
[...]
Ah. Dans ce cas, il faudrait effectivement tester autre chose. Il
semble que dans le cas de bash, on pourrait peut être tester:

if [ -n "${BASH}" ] ; then
do bash stuff
fi
[...]


[ -n "$BASH_VERSION" ]

mais je ne vois pas trop l'interet.

Suffit de mettre un

#! /usr/bin/env bash

en haut du script si on veut utiliser des features specific a
bash.


Je suis bien d'accord.
Je trouve bien plus facile de commencer un script par:


wget ftp://ftp.gnu.org/gnu/bash/bash-2.05.tar.bz2
tar jxf bash-2.05.tar.bz2
cd bash-2.05
../configure
make
make install
bash script.bash

que de s'embêter à faire des scripts "portables"...




"tar jxf" n'est pas portable ...



1 2 3