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

Parcours de fichier (avec blancs) et ajout de caracteres

15 réponses
Avatar
ozzii
Bonjour,

J'ai ceci sur sun (solaris):

#! /usr/bin/ksh
IFS=3D""
while read ligne
do
cc=3D`echo "$ligne"|cut -c120-120`
case $cc in
1) nli=3D"1"$ligne;;
*) nli=3D" "$ligne;;
esac
echo "${nli}"
done <$1
exit

Ce que je voudrais, c'est ajouter le chiffre 1 en d=E9but de ligne quand
je trouve 1 en position 120 et sinon rajouter un blanc. Tout ceci est
OK, mais cela prend un temps fou. Pour un fichier mis=E9reux de 3M, il
me met + de 10min.

Sinon, la moiti=E9 de mon probl=E8me c'est de faire un sed pour rajouter
un blanc en d=E9but de chaque ligne (et cela prend 1 sec). Mais il faut
quand m=EAme que je reparcours mon fichier pour faire la recherche du 1
en position 120.

Est-ce que quelqu'un =E0 une solution pour acc=E9l=E9rer le processus ?

Merci par avance

5 réponses

1 2
Avatar
Stephane Chazelas
2007-01-12, 13:17(+00), Luc Habert:
Christophe Leitienne :

Eviter les boucles "while read" en shell!



Peut-on savoir pourquoi ?


L'instruction read lit octet par octet sur stdin, résultat, ça
rrrrrrrrrraaaaaaaaaaaaaaaaaaaaaaaaammmmmmmmmmmmmmmmmeeeeeeee, comme le PO
l'a constaté.


C'est le moindre des problemes (et certains shells comme bash et
ksh le contourne quand l'input est seekable comme pour les
fichiers reguliers).

C'est plus une question de facon de programmer. Un shell est un
outil pour lancer des commandes. Programmer en shell veut dire
utiliser tous ces outils qui ont une fonction precise pour
qu'ils travaillent ensemble a accomplir une tache. Ce sont ces
outils font le boulot, le shell, c'est juste la glue.

Dans une boucle while read, on va faire appel des milliers de
fois a des outils qui ne vont meme pas travailler
cooperativement. Le shell ne fait pas le boulot, il prend
l'annuaire trouve le numero d'un plombier, lui demande de faire
un boulot. Trouve le numero d'un charpentier et d'un couvreur et
leur demande de s'arranger ensemble pour faire un toit.

Faire une boucle while read, c'est appeler un lecteur
professionel, lui demander de lire la premiere ligne d'un manuel
de plomberie, appeler un plombier, lui dire de devisser un
ecrou, rappeler un autre lecteur pour la deuxieme ligne, appeler
un autre plombier...

Sans parler de tous les autres problemes:

- La commande pour lire une ligne, ce n'est pas read mais
IFS= read -r. Sans le IFS=, les blanks en debut et fin sont
supprimés (et encore, ca depend des shells et de si il y a un
"" avant le blank en fin de ligne). Sans -r, les backslashs
sont interpretés comme des escapers de saut de ligne et de
separateurs (et supprimés)

- Manipuler des variables en shell est delicat. La plutpart des
gens ignorent qu'il faut les quoter (comme l'OP).

- dans:
while IFS= read -r line; do
cmd1; cmd2...
done < fichier
cmd1... ont perdu leur stdin original, vaudrait mieux faire:

while IFS= read -r line <&3; do
{
cmd1; cmd2
} 3<&-
done 3< fichier

- sans parler de l'utilisation d'echo (qui est une commande a
bannir) et des problemes habituels.

--
Stéphane



Avatar
Stephane Chazelas
2007-01-12, 01:37(-08), ozzii:
Bonjour,

J'ai ceci sur sun (solaris):

#! /usr/bin/ksh
IFS=""
while read ligne
do
cc=`echo "$ligne"|cut -c120-120`
case $cc in
1) nli="1"$ligne;;
*) nli=" "$ligne;;
esac
echo "${nli}"
done <$1
exit
[...]


Sinon, avec certaines versions de ksh, on peut faire

#! /usr/bin/ksh -
while IFS= read -r line; do
case $line in
({119}(?)1*)
line=1$line;;
(*)
line=" $line";;
esac
print -r -- "$line"
done < "${1?}"


Mais encore une fois, c'est *mal*.

--
Stéphane

Avatar
Ozzii
Stephane Chazelas avait prétendu :
2007-01-12, 01:37(-08), ozzii:
Sinon, avec certaines versions de ksh, on peut faire

#! /usr/bin/ksh -
while IFS= read -r line; do
case $line in
({119}(?)1*)
line=1$line;;
(*)
line=" $line";;
esac
print -r -- "$line"
done < "${1?}"


Mais encore une fois, c'est *mal*.


Merci pour cette info, mais j'ai utiliser le awk, et cela le fait tres
bien. A partir de maintenant, je vais essayer de n'utiliser que cela
pour les parcours des fichiers.

Avatar
Ozzii
Stephane Chazelas a pensé très fort :
2007-01-12, 13:17(+00), Luc Habert:
- sans parler de l'utilisation d'echo (qui est une commande a
bannir)


Quoi utiliser a la place? Moi, dasn tous me scripts (quand j'en ai
besoin), j'ai des echo.

Avatar
Stephane Chazelas
2007-01-13, 10:20(+01), Ozzii:
Stephane Chazelas a pensé très fort :
2007-01-12, 13:17(+00), Luc Habert:
- sans parler de l'utilisation d'echo (qui est une commande a
bannir)


Quoi utiliser a la place? Moi, dasn tous me scripts (quand j'en ai
besoin), j'ai des echo.
[...]


printf '%bn' "$var"

pour emuler les echo standard

printf '%sn' "$var"

pour emuler ce que tu crois que echo fait.

En gros,

echo -<whatever-but-n>

est censé affichier -<whatever-but-n><NL> chez POSIX comme chez
Unix. Meme bash qui est censé etre POSIX ne le respecte pas.

echo -n

est censé afficher "-n<NL>" chez Unix et avoir un resultat
unspecifié chez POSIX. Tres peu d'echos sont Unix conformant de
ce point de vue.

echo 't'

est censé afficher <Tab><NL> chez Unix et avoir un resultat
non-specifié chez POSIX.

En gros comme la plupart des echo sont au mieux POSIX
conformant, ca veut dire que pour une valeur quelconque
d'argument, typiquement, dans

echo "$var"

le resultat est non-specifié (ca peut afficher n'importe quoi)
(si $var commance par "-" ou "+" ou contient des "").


--
Stéphane


1 2