avec (pd)ksh (/bin/ksh de NetBSD), j'ai ca :
i=0
cat file | while read line
do
i=$(expr $i + 1)
done
echo "$i"
et j'obtiens... 0 !
Avec le ksh de Solaris 9 (ksh88 si je ne m'abuse), j'ai bien le nombre
de lignes dans file. La ou je commence a (encore) moins comprendre,
c'est que bash me fait pareil... tandis que zsh donne le resultat que
j'attends.
A cote de cela, le code suivant est evidemment ok avec bash, (pd)ksh et
zsh :
i=0
while (( $i < 10 ))
do
i=$(expr $i + 1)
done
echo $i
avec (pd)ksh (/bin/ksh de NetBSD), j'ai ca : i=0 cat file | while read line do i=$(expr $i + 1) done echo "$i" et j'obtiens... 0 !
Avec le ksh de Solaris 9 (ksh88 si je ne m'abuse), j'ai bien le nombre de lignes dans file. La ou je commence a (encore) moins comprendre, c'est que bash me fait pareil... tandis que zsh donne le resultat que j'attends.
A cote de cela, le code suivant est evidemment ok avec bash, (pd)ksh et zsh : i=0 while (( $i < 10 )) do i=$(expr $i + 1) done echo $i
Ou est-ce que je peche ?
Ton pêché est de croire que le shell est un langage de programmation. Si tu veux calculer une somme fais le avec un vrai langage de programmation. Par exemple:
#!/usr/bin/clisp -q -ansi (with-open-file (file "file") (print (loop for line = (read-line file nil nil) count 1)))
ou:
#!/usr/bin/clisp -q -ansi (print (loop with i = 0 while (< i 10) do (incf i 1) finally (return i)))
Sinon, la raison pour laquelle ça ne marche pas en shell, c'est parce qu'il fork des sous-processus quand tu utilise |, et que la variable i est incrémentée dans le sous-processus, pas dans le script de haut-niveau.
There is no worse tyranny than to force a man to pay for what he does not want merely because you think it would be good for him. -- Robert Heinlein
Pascal Cabaud <pcNOSP@Meila.jussieu.fr> writes:
Bonsoir,
avec (pd)ksh (/bin/ksh de NetBSD), j'ai ca :
i=0
cat file | while read line
do
i=$(expr $i + 1)
done
echo "$i"
et j'obtiens... 0 !
Avec le ksh de Solaris 9 (ksh88 si je ne m'abuse), j'ai bien le nombre
de lignes dans file. La ou je commence a (encore) moins comprendre,
c'est que bash me fait pareil... tandis que zsh donne le resultat que
j'attends.
A cote de cela, le code suivant est evidemment ok avec bash, (pd)ksh
et zsh :
i=0
while (( $i < 10 ))
do
i=$(expr $i + 1)
done
echo $i
Ou est-ce que je peche ?
Ton pêché est de croire que le shell est un langage de programmation.
Si tu veux calculer une somme fais le avec un vrai langage de programmation.
Par exemple:
#!/usr/bin/clisp -q -ansi
(with-open-file (file "file")
(print (loop for line = (read-line file nil nil) count 1)))
ou:
#!/usr/bin/clisp -q -ansi
(print (loop with i = 0 while (< i 10) do (incf i 1) finally (return i)))
Sinon, la raison pour laquelle ça ne marche pas en shell, c'est parce
qu'il fork des sous-processus quand tu utilise |, et que la variable i
est incrémentée dans le sous-processus, pas dans le script de haut-niveau.
avec (pd)ksh (/bin/ksh de NetBSD), j'ai ca : i=0 cat file | while read line do i=$(expr $i + 1) done echo "$i" et j'obtiens... 0 !
Avec le ksh de Solaris 9 (ksh88 si je ne m'abuse), j'ai bien le nombre de lignes dans file. La ou je commence a (encore) moins comprendre, c'est que bash me fait pareil... tandis que zsh donne le resultat que j'attends.
A cote de cela, le code suivant est evidemment ok avec bash, (pd)ksh et zsh : i=0 while (( $i < 10 )) do i=$(expr $i + 1) done echo $i
Ou est-ce que je peche ?
Ton pêché est de croire que le shell est un langage de programmation. Si tu veux calculer une somme fais le avec un vrai langage de programmation. Par exemple:
#!/usr/bin/clisp -q -ansi (with-open-file (file "file") (print (loop for line = (read-line file nil nil) count 1)))
ou:
#!/usr/bin/clisp -q -ansi (print (loop with i = 0 while (< i 10) do (incf i 1) finally (return i)))
Sinon, la raison pour laquelle ça ne marche pas en shell, c'est parce qu'il fork des sous-processus quand tu utilise |, et que la variable i est incrémentée dans le sous-processus, pas dans le script de haut-niveau.
There is no worse tyranny than to force a man to pay for what he does not want merely because you think it would be good for him. -- Robert Heinlein
Jean-Louis Liagre
Pascal Bourguignon wrote:
Pascal Cabaud writes:
Bonsoir,
avec (pd)ksh (/bin/ksh de NetBSD), j'ai ca : i=0 cat file | while read line do i=$(expr $i + 1) done echo "$i" et j'obtiens... 0 !
Avec le ksh de Solaris 9 (ksh88 si je ne m'abuse), j'ai bien le nombre de lignes dans file. La ou je commence a (encore) moins comprendre, c'est que bash me fait pareil... tandis que zsh donne le resultat que j'attends.
A cote de cela, le code suivant est evidemment ok avec bash, (pd)ksh et zsh : i=0 while (( $i < 10 )) do i=$(expr $i + 1) done echo $i
Ou est-ce que je peche ?
Ton pêché est de croire que le shell est un langage de programmation.
Non, ce problème est indépendant du langage de programmation, et je ne vois pas pourquoi les shells ne mériteraient pas cette appellation.
Après un fork, une variable se retrouve séparée en deux entités indépendantes, en shell, comme en C comme en tout langage supportant la création de nouveaux processus.
Le vrai problème ici est le manque de cohérence entre les différents shells quant au choix de la partie du pipeline à maintenir dans le shell courant.
Pascal Bourguignon wrote:
Pascal Cabaud <pcNOSP@Meila.jussieu.fr> writes:
Bonsoir,
avec (pd)ksh (/bin/ksh de NetBSD), j'ai ca :
i=0
cat file | while read line
do
i=$(expr $i + 1)
done
echo "$i"
et j'obtiens... 0 !
Avec le ksh de Solaris 9 (ksh88 si je ne m'abuse), j'ai bien le nombre
de lignes dans file. La ou je commence a (encore) moins comprendre,
c'est que bash me fait pareil... tandis que zsh donne le resultat que
j'attends.
A cote de cela, le code suivant est evidemment ok avec bash, (pd)ksh
et zsh :
i=0
while (( $i < 10 ))
do
i=$(expr $i + 1)
done
echo $i
Ou est-ce que je peche ?
Ton pêché est de croire que le shell est un langage de programmation.
Non, ce problème est indépendant du langage de programmation, et je ne vois pas
pourquoi les shells ne mériteraient pas cette appellation.
Après un fork, une variable se retrouve séparée en deux entités indépendantes,
en shell, comme en C comme en tout langage supportant la création de nouveaux
processus.
Le vrai problème ici est le manque de cohérence entre les différents shells
quant au choix de la partie du pipeline à maintenir dans le shell courant.
avec (pd)ksh (/bin/ksh de NetBSD), j'ai ca : i=0 cat file | while read line do i=$(expr $i + 1) done echo "$i" et j'obtiens... 0 !
Avec le ksh de Solaris 9 (ksh88 si je ne m'abuse), j'ai bien le nombre de lignes dans file. La ou je commence a (encore) moins comprendre, c'est que bash me fait pareil... tandis que zsh donne le resultat que j'attends.
A cote de cela, le code suivant est evidemment ok avec bash, (pd)ksh et zsh : i=0 while (( $i < 10 )) do i=$(expr $i + 1) done echo $i
Ou est-ce que je peche ?
Ton pêché est de croire que le shell est un langage de programmation.
Non, ce problème est indépendant du langage de programmation, et je ne vois pas pourquoi les shells ne mériteraient pas cette appellation.
Après un fork, une variable se retrouve séparée en deux entités indépendantes, en shell, comme en C comme en tout langage supportant la création de nouveaux processus.
Le vrai problème ici est le manque de cohérence entre les différents shells quant au choix de la partie du pipeline à maintenir dans le shell courant.
lhabert
Pascal Cabaud :
i=0 cat file | while read line do i=$(expr $i + 1) done echo "$i" et j'obtiens... 0 !
Les deux process reliés par le pipe sont lancés dans deux sous-shells. Donc les modifs de la variable i n'ont pas lieu dans le père...
Tu peux faire un :
i=0 cat file | { while read line do i=$(expr $i + 1) done echo "$i" }
pour y remédier. Enfin, pour ton cas particulier, tu peux aussi essayer un
while read line do i=$(expr $i + 1) done < file
, j'ose espérer qu'aucun shell ne va forker pour ça. Quelqu'un connait par coeur la norme?
Il y a cependant certains shells qui lancent la deuxième opérande du pipe dans le même shell, ce qui explique que ton code marchait avec certains...
Pascal Cabaud :
i=0
cat file | while read line
do
i=$(expr $i + 1)
done
echo "$i"
et j'obtiens... 0 !
Les deux process reliés par le pipe sont lancés dans deux sous-shells. Donc
les modifs de la variable i n'ont pas lieu dans le père...
Tu peux faire un :
i=0
cat file | {
while read line
do
i=$(expr $i + 1)
done
echo "$i"
}
pour y remédier. Enfin, pour ton cas particulier, tu peux aussi essayer un
while read line
do
i=$(expr $i + 1)
done < file
, j'ose espérer qu'aucun shell ne va forker pour ça. Quelqu'un connait par
coeur la norme?
Il y a cependant certains shells qui lancent la deuxième opérande du pipe
dans le même shell, ce qui explique que ton code marchait avec certains...
, j'ose espérer qu'aucun shell ne va forker pour ça. Quelqu'un connait par coeur la norme?
Au pire, il y aurait :
exec 3<&1 exec 1<file ... exec 1<&3 exec 3<&-
Stephane Chazelas
On Wed, 22 Feb 2006 08:23:50 +0000 (UTC), Luc Habert wrote: [...]
while read line do i=$(expr $i + 1) done < file
, j'ose espérer qu'aucun shell ne va forker pour ça. Quelqu'un connait par coeur la norme?
Le Bourne shell va forker. Les autres font des trucs louches, comme duppliquer le file descriptor 0 (et mettre le CLOSE ON EXEC dessus pour eviter de le passer a d'autres commandes) pour pouvoir le restaurer apres.
POSIX dit que le Bourne shell n'est pas conforme.
-- Stephane
On Wed, 22 Feb 2006 08:23:50 +0000 (UTC), Luc Habert wrote:
[...]
while read line
do
i=$(expr $i + 1)
done < file
, j'ose espérer qu'aucun shell ne va forker pour ça. Quelqu'un connait par
coeur la norme?
Le Bourne shell va forker. Les autres font des trucs louches,
comme duppliquer le file descriptor 0 (et mettre le CLOSE ON
EXEC dessus pour eviter de le passer a d'autres commandes) pour
pouvoir le restaurer apres.
On Wed, 22 Feb 2006 08:23:50 +0000 (UTC), Luc Habert wrote: [...]
while read line do i=$(expr $i + 1) done < file
, j'ose espérer qu'aucun shell ne va forker pour ça. Quelqu'un connait par coeur la norme?
Le Bourne shell va forker. Les autres font des trucs louches, comme duppliquer le file descriptor 0 (et mettre le CLOSE ON EXEC dessus pour eviter de le passer a d'autres commandes) pour pouvoir le restaurer apres.
POSIX dit que le Bourne shell n'est pas conforme.
-- Stephane
Vincent Lefevre
Dans l'article <dth72m$15mo$, Luc Habert écrit:
Il y a cependant certains shells qui lancent la deuxième opérande du pipe dans le même shell, ce qui explique que ton code marchait avec certains...
C'est ce que fait zsh pour cette raison. Dans zsh-users/4301:
zsh spawns a subshell for the LHS of a pipe, rather than the RHS, which lets you do things like
Sinon, la raison pour laquelle ça ne marche pas en shell, c'est parce qu'il fork des sous-processus quand tu utilise |, et que la variable i est incrémentée dans le sous-processus, pas dans le script de haut-niveau.
Forcement, c'etait sous mon nez :-/
Merci bien !
-- Pascal Cabaud
Pascal Bourguignon wrote:
Sinon, la raison pour laquelle ça ne marche pas en shell, c'est parce
qu'il fork des sous-processus quand tu utilise |, et que la variable i
est incrémentée dans le sous-processus, pas dans le script de haut-niveau.
Sinon, la raison pour laquelle ça ne marche pas en shell, c'est parce qu'il fork des sous-processus quand tu utilise |, et que la variable i est incrémentée dans le sous-processus, pas dans le script de haut-niveau.
Forcement, c'etait sous mon nez :-/
Merci bien !
-- Pascal Cabaud
Pascal Cabaud
bhamp0 wrote:
C'est quoi l'intérêt de ce "script" pour faire un comptage de lignes ? Pourquoi ne pas utiliser les commandes qui existent à la base (ici "wc -l") ?
Je n'allais pas poster 300 lignes quand 5 suffisent ;-)
-- Pascal Cabaud
bhamp0 wrote:
C'est quoi l'intérêt de ce "script" pour faire un comptage de lignes ?
Pourquoi ne pas utiliser les commandes qui existent à la base (ici "wc
-l") ?
Je n'allais pas poster 300 lignes quand 5 suffisent ;-)