Bonjour,
J'ai un petit problème avec mon script bash.
Je veux connaitre la ligne la plus longue d'un fichier texte: nom.txt
Il ressemble a ça:
=== Debut fichier ===
ILYA KOVALCHUK
BILL GUERIN
MARIUSZ CZERKAWSKI
MILAN HEJDUK
...
=== fin fichier ===
Voici le script que j'ai écrit:
=== Début du script ===
# /bin/bash
long_max=-1
nom="fooname"
cat < nom.txt | while true
do
read ligne
if [ "$ligne" = "" ];
then
echo "Le nom le plus long est : ${nom} avec ${long_max} caracteres."
break;
echo nothing!!!
fi
if [ ${#ligne} -gt ${long_max} ];
then
echo ========================================================
echo ${#ligne} $long_max $nom
nom=${ligne}
long_max=${#ligne}
echo ${#ligne} $long_max $nom
echo ---------------------------------------------------------
fi
done
echo "Le nom le plus long est : ${nom} avec ${long_max} caracteres."
exit
=== Fin script ===
Les valeurs des variables avant le "break" sont correctes.
Après la boucle, les variables contiennent les valeur initialisées:
fooname et -1
Pourquoi??
Red Hat 7.2
/bin/bash --version
GNU bash, version 2.05.8(1)-release (i386-redhat-linux-gnu)
Copyright 2000 Free Software Foundation, Inc.
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Stephane Chazelas
2003/11/19, 02:56(-05), Luc Martineau:
Je veux connaitre la ligne la plus longue d'un fichier texte: nom.txt Il ressemble a ça:
[...]
Voici le script que j'ai écrit:
C'est une erreur de "programmer" ça en shell. Les shells ne sont pas faits pour ça, ils sont fait pour appeler des utilitaires qui servent à faire le job.
awk est le plus approprié en l'occurrence :
awk 'length > m {m=length} END {printf "%.17gn", m}' < nom.txt
=== Début du script == > # /bin/bash
long_max=-1 nom="fooname"
cat < nom.txt | while true
cat est l'outil pour concaténer il est assez rare d'en avoir besoin. Ceci est un UUOC (useless use of cat) dans le jargon.
do read ligne
Si tu regardes la page de man, si tu ne passes pas l'option -r et si tu ne changes pas IFS, read fait des trucs en plus.
read lit un caractère à la fois (pour ne pas dépasser le n qui termine la ligne) sur un pipe, c'est carrément pas optimum.
if [ "$ligne" = "" ];
Pour tester la fin de fichier, il vaut mieux tester le code de retour de read. Il pourrait y avoir des lignes vides dans ton fichier.
[ -n "$ligne" ] ou [ "" = "$ligne" sont plus safes encore qu'avec les bash récents, il ne devrait pas y avoir de problème.
[...]
if [ ${#ligne} -gt ${long_max} ];
C'est toujours une bonne habitude de mettre des quotes autour des variables. Quand ce sont des nombres, il y a peu de chance qu'il y ait des problèmes, mais l'ajout des quotes devrait être automatique au moins pour avoir du code sémantiquement plus correct.
if [ "${#ligne}" -gt "${long_max}" ]
then echo ======================================================= > echo ${#ligne} $long_max $nom
Même chose
[...]
Les valeurs des variables avant le "break" sont correctes.
Après la boucle, les variables contiennent les valeur initialisées: fooname et -1
Pourquoi??
À cause de ton UUOC. Quand tu as un pipe, il faut que les deux commandes ou groupes de commandes qui sont de part et d'autre soient éxécutés dans un processus différent. Ici, pas de bol, ta boucle while était éxécutée dans un fils, le père n'a pas accès à ses variables.
max=0 while IFS= read <&3 -r ligne; do [ "${#ligne}" -gt "$max" ] && max=${#ligne} done 3< nom.txt
Si tu tiens à le faire en shell mais c'est une erreur amha.
Je veux connaitre la ligne la plus longue d'un fichier texte: nom.txt
Il ressemble a ça:
[...]
Voici le script que j'ai écrit:
C'est une erreur de "programmer" ça en shell. Les shells ne sont
pas faits pour ça, ils sont fait pour appeler des utilitaires
qui servent à faire le job.
awk est le plus approprié en l'occurrence :
awk 'length > m {m=length} END {printf "%.17gn", m}' < nom.txt
=== Début du script == >
# /bin/bash
long_max=-1
nom="fooname"
cat < nom.txt | while true
cat est l'outil pour concaténer il est assez rare d'en avoir
besoin. Ceci est un UUOC (useless use of cat) dans le jargon.
do
read ligne
Si tu regardes la page de man, si tu ne passes pas l'option -r
et si tu ne changes pas IFS, read fait des trucs en plus.
read lit un caractère à la fois (pour ne pas dépasser le n qui
termine la ligne) sur un pipe, c'est carrément pas optimum.
if [ "$ligne" = "" ];
Pour tester la fin de fichier, il vaut mieux tester le code de
retour de read. Il pourrait y avoir des lignes vides dans ton
fichier.
[ -n "$ligne" ] ou [ "" = "$ligne" sont plus safes encore
qu'avec les bash récents, il ne devrait pas y avoir de problème.
[...]
if [ ${#ligne} -gt ${long_max} ];
C'est toujours une bonne habitude de mettre des quotes autour
des variables. Quand ce sont des nombres, il y a peu de chance
qu'il y ait des problèmes, mais l'ajout des quotes devrait être
automatique au moins pour avoir du code sémantiquement plus
correct.
if [ "${#ligne}" -gt "${long_max}" ]
then
echo ======================================================= > echo ${#ligne} $long_max $nom
Même chose
[...]
Les valeurs des variables avant le "break" sont correctes.
Après la boucle, les variables contiennent les valeur initialisées:
fooname et -1
Pourquoi??
À cause de ton UUOC. Quand tu as un pipe, il faut que les deux
commandes ou groupes de commandes qui sont de part et d'autre
soient éxécutés dans un processus différent. Ici, pas de bol, ta
boucle while était éxécutée dans un fils, le père n'a pas accès
à ses variables.
max=0
while IFS= read <&3 -r ligne; do
[ "${#ligne}" -gt "$max" ] && max=${#ligne}
done 3< nom.txt
Si tu tiens à le faire en shell mais c'est une erreur amha.
Je veux connaitre la ligne la plus longue d'un fichier texte: nom.txt Il ressemble a ça:
[...]
Voici le script que j'ai écrit:
C'est une erreur de "programmer" ça en shell. Les shells ne sont pas faits pour ça, ils sont fait pour appeler des utilitaires qui servent à faire le job.
awk est le plus approprié en l'occurrence :
awk 'length > m {m=length} END {printf "%.17gn", m}' < nom.txt
=== Début du script == > # /bin/bash
long_max=-1 nom="fooname"
cat < nom.txt | while true
cat est l'outil pour concaténer il est assez rare d'en avoir besoin. Ceci est un UUOC (useless use of cat) dans le jargon.
do read ligne
Si tu regardes la page de man, si tu ne passes pas l'option -r et si tu ne changes pas IFS, read fait des trucs en plus.
read lit un caractère à la fois (pour ne pas dépasser le n qui termine la ligne) sur un pipe, c'est carrément pas optimum.
if [ "$ligne" = "" ];
Pour tester la fin de fichier, il vaut mieux tester le code de retour de read. Il pourrait y avoir des lignes vides dans ton fichier.
[ -n "$ligne" ] ou [ "" = "$ligne" sont plus safes encore qu'avec les bash récents, il ne devrait pas y avoir de problème.
[...]
if [ ${#ligne} -gt ${long_max} ];
C'est toujours une bonne habitude de mettre des quotes autour des variables. Quand ce sont des nombres, il y a peu de chance qu'il y ait des problèmes, mais l'ajout des quotes devrait être automatique au moins pour avoir du code sémantiquement plus correct.
if [ "${#ligne}" -gt "${long_max}" ]
then echo ======================================================= > echo ${#ligne} $long_max $nom
Même chose
[...]
Les valeurs des variables avant le "break" sont correctes.
Après la boucle, les variables contiennent les valeur initialisées: fooname et -1
Pourquoi??
À cause de ton UUOC. Quand tu as un pipe, il faut que les deux commandes ou groupes de commandes qui sont de part et d'autre soient éxécutés dans un processus différent. Ici, pas de bol, ta boucle while était éxécutée dans un fils, le père n'a pas accès à ses variables.
max=0 while IFS= read <&3 -r ligne; do [ "${#ligne}" -gt "$max" ] && max=${#ligne} done 3< nom.txt
Si tu tiens à le faire en shell mais c'est une erreur amha.
max=0 while IFS= read <&3 -r ligne; do [ "${#ligne}" -gt "$max" ] && max=${#ligne} done 3< nom.txt
Pourquoi un troisième fd ? Pour pas simplement : max=0 while IFS= read -r ligne; do [ "${#ligne}" -gt "$max" ] && max=${#ligne} done < nom.txt
-- Subject: Re: gravier j'ai acheter encarta 2001 de luxe j'aimerai le graver impossible a faire pour le moment -+- CP in <http://www.le-gnu.net> : À sec ou au gravier ? -+-
max=0
while IFS= read <&3 -r ligne; do
[ "${#ligne}" -gt "$max" ] && max=${#ligne}
done 3< nom.txt
Pourquoi un troisième fd ? Pour pas simplement :
max=0
while IFS= read -r ligne; do
[ "${#ligne}" -gt "$max" ] && max=${#ligne}
done < nom.txt
--
Subject: Re: gravier
j'ai acheter encarta 2001 de luxe j'aimerai le graver
impossible a faire pour le moment
-+- CP in <http://www.le-gnu.net> : À sec ou au gravier ? -+-
max=0 while IFS= read <&3 -r ligne; do [ "${#ligne}" -gt "$max" ] && max=${#ligne} done 3< nom.txt
Pourquoi un troisième fd ? Pour pas simplement : max=0 while IFS= read -r ligne; do [ "${#ligne}" -gt "$max" ] && max=${#ligne} done < nom.txt
-- Subject: Re: gravier j'ai acheter encarta 2001 de luxe j'aimerai le graver impossible a faire pour le moment -+- CP in <http://www.le-gnu.net> : À sec ou au gravier ? -+-
Stephane Chazelas
2003/11/19, 13:50(+01), Stephane Dupille:
max=0 while IFS= read <&3 -r ligne; do [ "${#ligne}" -gt "$max" ] && max=${#ligne} done 3< nom.txt
Pourquoi un troisième fd ? Pour pas simplement : max=0 while IFS= read -r ligne; do [ "${#ligne}" -gt "$max" ] && max=${#ligne} done < nom.txt
Si tu utilises le fd 0, l'entrée standard va être nom.txt pour toutes les commandes de ta boucle while alors que seule une (read) a besoin et surtout *doit* lire nom.txt. Ça ne pose pas de problème dans ce cas précis, mais ça en poserait dans d'autres, donc, c'est une bonne habitude d'utiliser un autre fd.
max=0
while IFS= read <&3 -r ligne; do
[ "${#ligne}" -gt "$max" ] && max=${#ligne}
done 3< nom.txt
Pourquoi un troisième fd ? Pour pas simplement :
max=0
while IFS= read -r ligne; do
[ "${#ligne}" -gt "$max" ] && max=${#ligne}
done < nom.txt
Si tu utilises le fd 0, l'entrée standard va être nom.txt pour
toutes les commandes de ta boucle while alors que seule une
(read) a besoin et surtout *doit* lire nom.txt. Ça ne pose pas
de problème dans ce cas précis, mais ça en poserait dans
d'autres, donc, c'est une bonne habitude d'utiliser un autre fd.
max=0 while IFS= read <&3 -r ligne; do [ "${#ligne}" -gt "$max" ] && max=${#ligne} done 3< nom.txt
Pourquoi un troisième fd ? Pour pas simplement : max=0 while IFS= read -r ligne; do [ "${#ligne}" -gt "$max" ] && max=${#ligne} done < nom.txt
Si tu utilises le fd 0, l'entrée standard va être nom.txt pour toutes les commandes de ta boucle while alors que seule une (read) a besoin et surtout *doit* lire nom.txt. Ça ne pose pas de problème dans ce cas précis, mais ça en poserait dans d'autres, donc, c'est une bonne habitude d'utiliser un autre fd.
C'est une erreur de "programmer" ça en shell. Les shells ne sont pas faits pour ça, ils sont fait pour appeler des utilitaires qui servent à faire le job.
awk est le plus approprié en l'occurrence :
awk 'length > m {m=length} END {printf "%.17gn", m}' < nom.txt
Je savais qu'il existait des méthodes beaucoup plus performantes.
Je préfère de loin avoir un script facilement lisible prenant au pire quelques secondes à s'exécuter.
Je vais faire un peu de lecture, awk, sed... J'ai eu toute une leçon.
Merci beaucoup
Luc
Stephane Chazelas wrote:
2003/11/19, 02:56(-05), Luc Martineau:
C'est une erreur de "programmer" ça en shell. Les shells ne sont
pas faits pour ça, ils sont fait pour appeler des utilitaires
qui servent à faire le job.
awk est le plus approprié en l'occurrence :
awk 'length > m {m=length} END {printf "%.17gn", m}' < nom.txt
Je savais qu'il existait des méthodes beaucoup plus performantes.
Je préfère de loin avoir un script facilement lisible prenant au pire
quelques secondes à s'exécuter.
Je vais faire un peu de lecture, awk, sed...
J'ai eu toute une leçon.
C'est une erreur de "programmer" ça en shell. Les shells ne sont pas faits pour ça, ils sont fait pour appeler des utilitaires qui servent à faire le job.
awk est le plus approprié en l'occurrence :
awk 'length > m {m=length} END {printf "%.17gn", m}' < nom.txt
Je savais qu'il existait des méthodes beaucoup plus performantes.
Je préfère de loin avoir un script facilement lisible prenant au pire quelques secondes à s'exécuter.
Je vais faire un peu de lecture, awk, sed... J'ai eu toute une leçon.
Merci beaucoup
Luc
Pascal Bourguignon
Stephane Chazelas writes:
2003/11/19, 02:56(-05), Luc Martineau:
Je veux connaitre la ligne la plus longue d'un fichier texte: nom.txt Il ressemble a ça:
[...]
Voici le script que j'ai écrit:
C'est une erreur de "programmer" ça en shell. Les shells ne sont pas faits pour ça, ils sont fait pour appeler des utilitaires qui servent à faire le job.
awk est le plus approprié en l'occurrence :
awk 'length > m {m=length} END {printf "%.17gn", m}' < nom.txt
[...]
max=0 while IFS= read <&3 -r ligne; do [ "${#ligne}" -gt "$max" ] && max=${#ligne} done 3< nom.txt
Si tu tiens à le faire en shell mais c'est une erreur amha.
Mais si c'est un petit fichier, c'est plus efficace de le faire dans bash que de forker un nouveau processus!
Même si c'est un gros fichier, ça ne doit pas faire une grosse différence: c'est que de l'entrée/sortie et awk est aussi interprété!
Ceci dit, je suis d'accord que pour faire de l'algorithme, les shells ne sont pas adaptés. Utiliser clisp ou scsh!
Je veux connaitre la ligne la plus longue d'un fichier texte: nom.txt
Il ressemble a ça:
[...]
Voici le script que j'ai écrit:
C'est une erreur de "programmer" ça en shell. Les shells ne sont
pas faits pour ça, ils sont fait pour appeler des utilitaires
qui servent à faire le job.
awk est le plus approprié en l'occurrence :
awk 'length > m {m=length} END {printf "%.17gn", m}' < nom.txt
[...]
max=0
while IFS= read <&3 -r ligne; do
[ "${#ligne}" -gt "$max" ] && max=${#ligne}
done 3< nom.txt
Si tu tiens à le faire en shell mais c'est une erreur amha.
Mais si c'est un petit fichier, c'est plus efficace de le faire dans
bash que de forker un nouveau processus!
Même si c'est un gros fichier, ça ne doit pas faire une grosse
différence: c'est que de l'entrée/sortie et awk est aussi interprété!
Ceci dit, je suis d'accord que pour faire de l'algorithme, les shells
ne sont pas adaptés. Utiliser clisp ou scsh!
Je veux connaitre la ligne la plus longue d'un fichier texte: nom.txt Il ressemble a ça:
[...]
Voici le script que j'ai écrit:
C'est une erreur de "programmer" ça en shell. Les shells ne sont pas faits pour ça, ils sont fait pour appeler des utilitaires qui servent à faire le job.
awk est le plus approprié en l'occurrence :
awk 'length > m {m=length} END {printf "%.17gn", m}' < nom.txt
[...]
max=0 while IFS= read <&3 -r ligne; do [ "${#ligne}" -gt "$max" ] && max=${#ligne} done 3< nom.txt
Si tu tiens à le faire en shell mais c'est une erreur amha.
Mais si c'est un petit fichier, c'est plus efficace de le faire dans bash que de forker un nouveau processus!
Même si c'est un gros fichier, ça ne doit pas faire une grosse différence: c'est que de l'entrée/sortie et awk est aussi interprété!
Ceci dit, je suis d'accord que pour faire de l'algorithme, les shells ne sont pas adaptés. Utiliser clisp ou scsh!
Mais si c'est un petit fichier, c'est plus efficace de le faire dans bash que de forker un nouveau processus!
Et si c'est un petit fichier, on s'en fout un peu que ça se fasse en 0.001s ou 0.01, Alors que sur un gros on fait la différence entre 10s et 100s.
Même si c'est un gros fichier, ça ne doit pas faire une grosse différence: c'est que de l'entrée/sortie et awk est aussi interprété!
bash a un work around au fait que read ne peut lire qu'un byte à la fois quand l'input est un fichier, donc, ça ne sera pas aussi lamentable qu'avec d'autres shells, mais je parlais surtout de considérations de design en fait.
Ceci dit, je suis d'accord que pour faire de l'algorithme, les shells ne sont pas adaptés. Utiliser clisp ou scsh!
Mais si c'est un petit fichier, c'est plus efficace de le faire dans
bash que de forker un nouveau processus!
Et si c'est un petit fichier, on s'en fout un peu que ça se
fasse en 0.001s ou 0.01, Alors que sur un gros on fait la
différence entre 10s et 100s.
Même si c'est un gros fichier, ça ne doit pas faire une grosse
différence: c'est que de l'entrée/sortie et awk est aussi interprété!
bash a un work around au fait que read ne peut lire qu'un byte à
la fois quand l'input est un fichier, donc, ça ne sera pas aussi
lamentable qu'avec d'autres shells, mais je parlais surtout de
considérations de design en fait.
Ceci dit, je suis d'accord que pour faire de l'algorithme, les shells
ne sont pas adaptés. Utiliser clisp ou scsh!
Mais si c'est un petit fichier, c'est plus efficace de le faire dans bash que de forker un nouveau processus!
Et si c'est un petit fichier, on s'en fout un peu que ça se fasse en 0.001s ou 0.01, Alors que sur un gros on fait la différence entre 10s et 100s.
Même si c'est un gros fichier, ça ne doit pas faire une grosse différence: c'est que de l'entrée/sortie et awk est aussi interprété!
bash a un work around au fait que read ne peut lire qu'un byte à la fois quand l'input est un fichier, donc, ça ne sera pas aussi lamentable qu'avec d'autres shells, mais je parlais surtout de considérations de design en fait.
Ceci dit, je suis d'accord que pour faire de l'algorithme, les shells ne sont pas adaptés. Utiliser clisp ou scsh!
Mais si c'est un petit fichier, c'est plus efficace de le faire dans bash que de forker un nouveau processus!
Et si c'est un petit fichier, on s'en fout un peu que ça se fasse en 0.001s ou 0.01, Alors que sur un gros on fait la différence entre 10s et 100s.
Même si c'est un gros fichier, ça ne doit pas faire une grosse différence: c'est que de l'entrée/sortie et awk est aussi interprété!
bash a un work around au fait que read ne peut lire qu'un byte à la fois quand l'input est un fichier, donc, ça ne sera pas aussi lamentable qu'avec d'autres shells, mais je parlais surtout de considérations de design en fait.
Je ne m'attendais pas à ça: bash est bien plus lent à lire que awk ou que wc:
[ tmp]$ od < asfuwx5ID | time bash -c 'while read line ; do : ; done' 15.91user 15.45system 0:45.43elapsed 69%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (525major+193minor)pagefaults 0swaps
[ tmp]$ od < asfuwx5ID | time awk '{i++;}' 0.38user 0.01system 0:01.78elapsed 21%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (173major+24minor)pagefaults 0swaps
[ tmp]$ od < asfuwx5ID | time wc 258246 2324201 16654827 0.43user 0.01system 0:01.92elapsed 22%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (131major+17minor)pagefaults 0swaps
Ceci dit, je suis d'accord que pour faire de l'algorithme, les shells ne sont pas adaptés. Utiliser clisp ou scsh!
Mais si c'est un petit fichier, c'est plus efficace de le faire dans
bash que de forker un nouveau processus!
Et si c'est un petit fichier, on s'en fout un peu que ça se
fasse en 0.001s ou 0.01, Alors que sur un gros on fait la
différence entre 10s et 100s.
Même si c'est un gros fichier, ça ne doit pas faire une grosse
différence: c'est que de l'entrée/sortie et awk est aussi interprété!
bash a un work around au fait que read ne peut lire qu'un byte à
la fois quand l'input est un fichier, donc, ça ne sera pas aussi
lamentable qu'avec d'autres shells, mais je parlais surtout de
considérations de design en fait.
Je ne m'attendais pas à ça: bash est bien plus lent à lire que awk ou que wc:
[pascal@thalassa tmp]$ od < asfuwx5ID | time bash -c 'while read line ; do : ; done'
15.91user 15.45system 0:45.43elapsed 69%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (525major+193minor)pagefaults 0swaps
[pascal@thalassa tmp]$ od < asfuwx5ID | time awk '{i++;}'
0.38user 0.01system 0:01.78elapsed 21%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (173major+24minor)pagefaults 0swaps
[pascal@thalassa tmp]$ od < asfuwx5ID | time wc
258246 2324201 16654827
0.43user 0.01system 0:01.92elapsed 22%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (131major+17minor)pagefaults 0swaps
Ceci dit, je suis d'accord que pour faire de l'algorithme, les shells
ne sont pas adaptés. Utiliser clisp ou scsh!
Mais si c'est un petit fichier, c'est plus efficace de le faire dans bash que de forker un nouveau processus!
Et si c'est un petit fichier, on s'en fout un peu que ça se fasse en 0.001s ou 0.01, Alors que sur un gros on fait la différence entre 10s et 100s.
Même si c'est un gros fichier, ça ne doit pas faire une grosse différence: c'est que de l'entrée/sortie et awk est aussi interprété!
bash a un work around au fait que read ne peut lire qu'un byte à la fois quand l'input est un fichier, donc, ça ne sera pas aussi lamentable qu'avec d'autres shells, mais je parlais surtout de considérations de design en fait.
Je ne m'attendais pas à ça: bash est bien plus lent à lire que awk ou que wc:
[ tmp]$ od < asfuwx5ID | time bash -c 'while read line ; do : ; done' 15.91user 15.45system 0:45.43elapsed 69%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (525major+193minor)pagefaults 0swaps
[ tmp]$ od < asfuwx5ID | time awk '{i++;}' 0.38user 0.01system 0:01.78elapsed 21%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (173major+24minor)pagefaults 0swaps
[ tmp]$ od < asfuwx5ID | time wc 258246 2324201 16654827 0.43user 0.01system 0:01.92elapsed 22%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (131major+17minor)pagefaults 0swaps
Ceci dit, je suis d'accord que pour faire de l'algorithme, les shells ne sont pas adaptés. Utiliser clisp ou scsh!
bash a un work around au fait que read ne peut lire qu'un byte à la fois quand l'input est un fichier, donc, ça ne sera pas aussi ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lamentable qu'avec d'autres shells, mais je parlais surtout de considérations de design en fait.
Je ne m'attendais pas à ça: bash est bien plus lent à lire que awk ou que wc:
[ tmp]$ od < asfuwx5ID | time bash -c 'while read line ; do : ; done' 15.91user 15.45system 0:45.43elapsed 69%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (525major+193minor)pagefaults 0swaps [...]
Quand l'input est un fichier, il lit par bloc et fait des lseeks en arrière quand il lance des commandes externes (dans mon exemple, il n'y avait pas de commande externe et l'input était un fichier).
Quand, l'input est un pipe comme dans ton exemple, il est obligé de lire caractère par caractère.
Évidemment, ça reste lent. ksh93 est un peu plus rapide et a le même genre d'optimisation. zsh n'a pas ce genre d'optimisation mais est plus rapide sur les pipes.
Note que l'awk de GNU est globalement plus lent que les autres implémentations d'awk (surtout dans les locales utf-8).
bash a un work around au fait que read ne peut lire qu'un byte à
la fois quand l'input est un fichier, donc, ça ne sera pas aussi
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lamentable qu'avec d'autres shells, mais je parlais surtout de
considérations de design en fait.
Je ne m'attendais pas à ça: bash est bien plus lent à lire que awk ou que wc:
[pascal@thalassa tmp]$ od < asfuwx5ID | time bash -c 'while read line ; do : ; done'
15.91user 15.45system 0:45.43elapsed 69%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (525major+193minor)pagefaults 0swaps
[...]
Quand l'input est un fichier, il lit par bloc et fait des lseeks
en arrière quand il lance des commandes externes (dans mon
exemple, il n'y avait pas de commande externe et l'input était
un fichier).
Quand, l'input est un pipe comme dans ton exemple, il est obligé
de lire caractère par caractère.
Évidemment, ça reste lent. ksh93 est un peu plus rapide et a le
même genre d'optimisation. zsh n'a pas ce genre d'optimisation
mais est plus rapide sur les pipes.
Note que l'awk de GNU est globalement plus lent que les autres
implémentations d'awk (surtout dans les locales utf-8).
bash a un work around au fait que read ne peut lire qu'un byte à la fois quand l'input est un fichier, donc, ça ne sera pas aussi ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lamentable qu'avec d'autres shells, mais je parlais surtout de considérations de design en fait.
Je ne m'attendais pas à ça: bash est bien plus lent à lire que awk ou que wc:
[ tmp]$ od < asfuwx5ID | time bash -c 'while read line ; do : ; done' 15.91user 15.45system 0:45.43elapsed 69%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (525major+193minor)pagefaults 0swaps [...]
Quand l'input est un fichier, il lit par bloc et fait des lseeks en arrière quand il lance des commandes externes (dans mon exemple, il n'y avait pas de commande externe et l'input était un fichier).
Quand, l'input est un pipe comme dans ton exemple, il est obligé de lire caractère par caractère.
Évidemment, ça reste lent. ksh93 est un peu plus rapide et a le même genre d'optimisation. zsh n'a pas ce genre d'optimisation mais est plus rapide sur les pipes.
Note que l'awk de GNU est globalement plus lent que les autres implémentations d'awk (surtout dans les locales utf-8).
la fois quand l'input est un fichier, donc, ça ne sera pas aussi ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Quand l'input est un fichier, il lit par bloc et fait des lseeks en arrière quand il lance des commandes externes (dans mon exemple, il n'y avait pas de commande externe et l'input était un fichier).
Quand, l'input est un pipe comme dans ton exemple, il est obligé de lire caractère par caractère.
Ça prouve le succès psychologique des pipes, si je ne fais plus la différence entre un pipe et un fichier!
la fois quand l'input est un fichier, donc, ça ne sera pas aussi
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Quand l'input est un fichier, il lit par bloc et fait des lseeks
en arrière quand il lance des commandes externes (dans mon
exemple, il n'y avait pas de commande externe et l'input était
un fichier).
Quand, l'input est un pipe comme dans ton exemple, il est obligé
de lire caractère par caractère.
Ça prouve le succès psychologique des pipes, si je ne fais plus la
différence entre un pipe et un fichier!
la fois quand l'input est un fichier, donc, ça ne sera pas aussi ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Quand l'input est un fichier, il lit par bloc et fait des lseeks en arrière quand il lance des commandes externes (dans mon exemple, il n'y avait pas de commande externe et l'input était un fichier).
Quand, l'input est un pipe comme dans ton exemple, il est obligé de lire caractère par caractère.
Ça prouve le succès psychologique des pipes, si je ne fais plus la différence entre un pipe et un fichier!