Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[for] fonctionnalité zsh à reproduire sous bsh

11 réponses
Avatar
David LE BOURGEOIS
Bonjour.

Je suis confronté à un petit soucis concernant les espaces dans une
boucle for. Je m'explique :

david@abeille ~/tmp $ echo $SHELL
/bin/zsh
david@abeille ~/tmp $ a="1 2 3"
david@abeille ~/tmp $ for i in $a ; do echo "[$i]" ; done
[1 2 3]
david@abeille ~/tmp $ /bin/sh
sh-2.04$ a="1 2 3"
sh-2.04$ for i in $a ; do echo "[$i]" ; done
[1]
[2]
[3]

Comment puis-je reproduire cette interprétation correcte de zsh dans sh
(ou ksh) ?

Je suis en fait face au problème des noms de fichiers contenant des
espaces. Et même en protégeant l'espace par un \, l'interprétation reste
la même. J'ai aussi essayé avec les quotes, mais sans succès.
Par exemple :

$ fichiers="
f1
fichier n2
'fichier numéro 3'
"

Merci de répondre à cette question un peu triviale, mais là je sèche :-).

David.

10 réponses

1 2
Avatar
Laurent Wacrenier
David LE BOURGEOIS écrit:
Bonjour.

Je suis confronté à un petit soucis concernant les espaces dans une
boucle for. Je m'explique :

~/tmp $ echo $SHELL
/bin/zsh
~/tmp $ a="1 2 3"
~/tmp $ for i in $a ; do echo "[$i]" ; done
[1 2 3]
~/tmp $ /bin/sh
sh-2.04$ a="1 2 3"
sh-2.04$ for i in $a ; do echo "[$i]" ; done
[1]
[2]
[3]

Comment puis-je reproduire cette interprétation correcte de zsh dans sh
(ou ksh) ?


for i in "$a" ; do echo "[$i]" ; done

C'est une option de zsh (shwordsplit), je ne suis pas sûr qu'elle soit
bien correcte.

Avatar
Stephane CHAZELAS
Le Tue, 30 Sep 2003 18:22:30 +0200, David LE BOURGEOIS écrivait :
Je suis confronté à un petit soucis concernant les espaces dans une
boucle for. Je m'explique :

~/tmp $ echo $SHELL
/bin/zsh
~/tmp $ a="1 2 3"
~/tmp $ for i in $a ; do echo "[$i]" ; done
[1 2 3]
~/tmp $ /bin/sh
sh-2.04$ a="1 2 3"
sh-2.04$ for i in $a ; do echo "[$i]" ; done
[1]
[2]
[3]

Comment puis-je reproduire cette interprétation correcte de zsh dans sh
(ou ksh) ?


IFS=; set -f; unset FIGNORE GLOBIGNORE; LC_ALL=POSIX; LANG=POSIX

à mettre au début du script.

ou alors,

for i in "$a"; do printf '%sn' "[$i]"; done

--
Stéphane

Avatar
Stephane CHAZELAS
Le Tue, 30 Sep 2003 16:34:02 +0000 (UTC), Laurent Wacrenier écrivait :
[...]
C'est une option de zsh (shwordsplit), je ne suis pas sûr qu'elle soit
bien correcte.


Qui, par défaut, est désactivée.

Sur le fait que ce soit correct ou pas,
voir http://zsh.sunsite.dk/FAQ/zshfaq03.html#l17

--
Stéphane

Avatar
Laurent Wacrenier
Stephane CHAZELAS écrit:
C'est une option de zsh (shwordsplit), je ne suis pas sûr qu'elle soit
bien correcte.


Qui, par défaut, est désactivée.

Sur le fait que ce soit correct ou pas,
voir http://zsh.sunsite.dk/FAQ/zshfaq03.html#l17


Le fait est que sur sh on peut se débarasser du découpage en mettant
la variable entre "". Il n'y a pas trop d'interêt à forcer cette
interprétation et en alourdissant la syntaxe lorsque qu'on a besoin de
découper. Celà est de plus incompatible avec les shells connus.


Avatar
David LE BOURGEOIS



for i in "$a"; do printf '%sn' "[$i]"; done



Au poil, merci.

A plus.

Avatar
Stephane CHAZELAS
Le Tue, 30 Sep 2003 17:02:29 +0000 (UTC), Laurent Wacrenier écrivait :
[...]
Le fait est que sur sh on peut se débarasser du découpage en mettant
la variable entre ""


On n'a quasi jamais besoin du découpage. D'un autre coté, les
gens oublient quasi-systematiquement de mettre des double
quotes autour des variables (quand il ne doit pas y avoir de
découpage ou de génération de noms de fichiers) et les problèmes
ne surviennent alors pas toujours immédiatement.

Les nouveaux (1988!) shells comme bash, ksh, zsh ont les
tableaux, il n'est donc quasiment plus jamais nécessaire
aujourd'hui de recourir au "word splitting".

zsh a un typage cohérent ; l'expansion d'un "array", d'un
"scalar" d'un "integer" est toujours cohérent.

En zsh, on fait

scalar="multi word value"
cmd $scalar

array=($=var) array2=(multiple words)
for iterator in $array; do ...; done
ou encore:
for iterator ($=var) { ... }

Je ne vous mets pas l'équivalent ksh, par déscence

Il n'y a pas trop d'interêt à forcer cette
interprétation et en alourdissant la syntaxe lorsque qu'on a besoin de
découper.


mettre des guillemets autour de toutes les variables est à mon
sens beaucoup plus lourd, ainsi que le "${array[@]}" des bash et
ksh.

Entre:

cmd="grep"
args=(-e "test 1" -e "test 2")
$cmd $args

et:

cmd="grep"
set -A args -- -e "test 1" -e "test 2"
"$cmd" "${args[@]}"

Quel est le plus lourd ?


Celà est de plus incompatible avec les shells connus.


Quels shells connus ? Tous les shells sont incompatibles entre
eux. zsh a un mode de compatibilité sh ou ksh.

zsh s'est un peu inspiré de rc qui lui non-plus n'est pas
"compatible avec les shells connus" mais beaucoup plus cohérent
que ksh et ses clones.

--
Stéphane

Avatar
Laurent Wacrenier
Stephane CHAZELAS écrit:
Le Tue, 30 Sep 2003 17:02:29 +0000 (UTC), Laurent Wacrenier écrivait :
[...]
Le fait est que sur sh on peut se débarasser du découpage en mettant
la variable entre ""


On n'a quasi jamais besoin du découpage. D'un autre coté, les


On ne doit pas faire les mêmes programmes, parce que j'utilise
fréquement des listes et j'aime bien pouvoir naviguer dedans.

gens oublient quasi-systematiquement de mettre des double
quotes autour des variables (quand il ne doit pas y avoir de
découpage ou de génération de noms de fichiers) et les problèmes
ne surviennent alors pas toujours immédiatement.


Un programme mal fait doit avoir le plus d'erreurs possibles pour
qu'on detecte le plus rapidement possible qu'il est mal fait.


Avatar
Stephane CHAZELAS
Le Tue, 30 Sep 2003 20:00:46 +0000 (UTC), Laurent Wacrenier écrivait :
Stephane CHAZELAS écrit:
Le Tue, 30 Sep 2003 17:02:29 +0000 (UTC), Laurent Wacrenier écrivait :
[...]
Le fait est que sur sh on peut se débarasser du découpage en mettant
la variable entre ""


On n'a quasi jamais besoin du découpage. D'un autre coté, les


On ne doit pas faire les mêmes programmes, parce que j'utilise
fréquement des listes et j'aime bien pouvoir naviguer dedans.


Quelle rapport avec les listes? Si tu navigues avec des listes
en utilisant le "word splitting", il y a de grandes chances que
tes programmes soient buggués. Perso, je ne navigue pas dans des
listes en sh. Si j'en viens à ce degré de complexité, j'utilise
awk, perl ou C.

gens oublient quasi-systematiquement de mettre des double
quotes autour des variables (quand il ne doit pas y avoir de
découpage ou de génération de noms de fichiers) et les problèmes
ne surviennent alors pas toujours immédiatement.


Un programme mal fait doit avoir le plus d'erreurs possibles pour
qu'on detecte le plus rapidement possible qu'il est mal fait.


Mauvaise foi detected.

Dans un *langage* bien fait, les erreurs apparaissent le plus
tot possible. Exemple, Ada est un langage bien fait, ksh93 est
un langage mal fait. Il est plus difficile d'écrire un programme
mal fait avec un langage bien fait, la discussion ne portait pas
sur les pratiques des utilisateur mais sur la qualité des
langages/interpreteurs..

Exemple:

cmd -?

marchera très longtemps avec bash ou ksh... jusqu'au jour où il
y aura un fichier "-p" dans le répertoire courant.
(un script avec une telle erreur écrit par David Korn himself:
http://www.research.att.com/~dgk/ksh/script/env)
Avec zsh, à moins qu'il y ait un fichier qui matche "-?" dans le
répertoire courant, on aura immédiatement:
zsh: no matches found: -?
l'erreur est détectée très tot (c'est une autre incompatibilité
de zsh)

cd $1
Marchera très longtemps, jusqu'à ce qu'un jour le répertoire
s'appelle "foo bar" ou "***"...
Avec zsh, tant qu'on ne fait pas « cd $~=1 » à la place, on n'a
pas ce genre de problème.
Note qu'en l'occurrence, pour etre tranquille, il aurait fallu
écrire: cd -- "$1", combien de fois as-tu vu ce genre de
précaution prise dans un script ?

Avec les shells bourne, les variables sont de type "string" sauf
parfois où elles sont considérées comme des listes voire comme
des patterns de fichiers. Le shell rc est plus cohérent, toute
les variables sont des listes, il faut explicitement faire $^var
pour joindre les éléments de la liste en une chaine de
caractères.

C'est avec ksh (et bash) qu'on arrive au summum: les variables
sont des tableaux, qui sont parfois considérées comme des
chaines, parfois comme des listes (mais qui ne comprennent pas
les éléments du tableau) parfois comme des patterns de fichiers,
parfois comme des brace expressions.

Exemple (ksh93):
a="{*,t}" ou a=("{*,t}") ou a[0]="{*,t}"
a est un tableau à 1 élément d'indice 0 mais dans
echo $a
$a sera substitué par une liste d'arguments : la liste des
fichiers dans le répertoire courant suivi de "t", alors que
${#a[@]} donne "1". (et encore, "$a" ne contient aucun caractère
d'IFS).
echo "$a": "$a" substitué par "{*,t}"

Dans b[1]=*
b est un tableau à un élément ou une chaine vide
echo $b ne donne rien,
echo "${b[@]}" renvoie "*", ${b[@]} une liste de fichiers

a=() est en fait équivalent à "unset a", qui le sait ?

--
Stéphane



Avatar
Laurent Wacrenier
Stephane CHAZELAS écrit:
On ne doit pas faire les mêmes programmes, parce que j'utilise
fréquement des listes et j'aime bien pouvoir naviguer dedans.


Quelle rapport avec les listes? Si tu navigues avec des listes
en utilisant le "word splitting", il y a de grandes chances que
tes programmes soient buggués. Perso, je ne navigue pas dans des
listes en sh. Si j'en viens à ce degré de complexité, j'utilise
awk, perl ou C.


Je ne vois pas le mal à déclarer une liste au début d'un programme,
afin de pouvoir la faire évoluer avec les besoins puis de faire le
traitement dans le corp du programme.

liste_de_trucs_a_faire="truc1 truc2 truc3"

...

for truc in $liste_de_trucs_a_faire
do
faire $truc
done


Avatar
Stephane CHAZELAS
Le Wed, 1 Oct 2003 09:03:46 +0000 (UTC), Laurent Wacrenier écrivait :
[...]
Je ne vois pas le mal à déclarer une liste au début d'un programme,
afin de pouvoir la faire évoluer avec les besoins puis de faire le
traitement dans le corp du programme.

liste_de_trucs_a_faire="truc1 truc2 truc3"

...

for truc in $liste_de_trucs_a_faire
do
faire $truc
done


Moi non-plus. Note que tu vas etre embeté, le jour où tu voudras
des " ", "*", "?", "{" dans les items. Ya toujours moyen de
contourner, mais c'est quand-meme beaucoup plus facile avec des
variables de *type* liste. Seul zsh a ce typage. Pour ksh/bash,
c'est de la sale bidouille pour garder une compatibilité.

--
Stéphane

1 2