Précédent   Forum des professionnels en informatique > Systèmes > Linux > Applications > Shell
Shell Vos questions sur l'utilisation des commandes shell
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 10/09/2008, 14h17   #1
Invité régulier
 
Inscription : juin 2007
Messages : 13
Détails du profil
Informations forums :
Inscription : juin 2007
Messages : 13
Points : 6
Points : 6
Par défaut Accés direct dans un gros fichier ?

Bonjour,

Soit un gros fichier d'environ 90 000 lignes (mais ça peut varier légèrement) dans lequel j'ai besoin de récupérer le contenu d'un numéro de ligne déterminé aléatoirement

En KSH, j'ai donc écrit le bout de code suivant
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
 
#! /bin/ksh
 
# Mon gros fichier
fileEntree=$1
# Nombre de ligne dans le fichier
nbEntree=`cat $fileEntree | wc -l`
 
# numéro de la ligne a atteindre
numEntree=$RANDOM
# Modulo
let "numEntree %= $nbEntree"
 
# récupération de la ligne par head et tail
entree=`head -${numEntree} $fileEntree | tail -1`
echo "entree = "$entree
Ca marche bien mais le problème, c'est lent, bcp trop lent (2 secondes pour remonter la valeur).
Or ce bout de code fonctionne dans un autre script et au total, ca met 48h ! (Si je le désactive, ca ne mets "que" 4h)

Je cherche donc une autre méthode plus rapide.

J'ai envisagé de mettre le fichier dans un tableau ksh mais comme la taille du tableau est limité à 4096, ca ne marche pas.

Est-ce qu'il existe une méthode ou fonction du côté de perl ou awk ou ... pour faire un accés direct dans un fichier à partir du numéro de ligne ?

D'avance merci
david2109 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/09/2008, 14h41   #2
Membre éprouvé
 
Avatar de Tchetch
 
Inscription : mars 2002
Messages : 401
Détails du profil
Informations personnelles :
Âge : 27

Informations forums :
Inscription : mars 2002
Messages : 401
Points : 434
Points : 434
Est-ce que tu peux connaitre la position en terme d'octet, tu peux faire en C (mais il dois y avoir un équivalent en Perl, PHP, ...) fopen et fseek.
Mais tu t'en sortiras mieux avec un script en Perl et une boucle ou un programme compilé que en shell. Là tu lances plusieurs processus, ça coûte du temps au système tout ça.
__________________
Mon wiki (on y parle Debian principalement) : http://www.tchetch.net/
Tchetch est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/09/2008, 15h14   #3
Invité régulier
 
Inscription : juin 2007
Messages : 13
Détails du profil
Informations forums :
Inscription : juin 2007
Messages : 13
Points : 6
Points : 6
Bonjour,

Hélas non, je n'ai pas trop la possibilité de connaitre la position en terme d'octets : les lignes sont de 2 tailles différentes (8 ou 11 caractères)

Je vais voir si du coté Perl, il y a une solution.
david2109 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/09/2008, 15h25   #4
Membre éprouvé
 
Avatar de Tchetch
 
Inscription : mars 2002
Messages : 401
Détails du profil
Informations personnelles :
Âge : 27

Informations forums :
Inscription : mars 2002
Messages : 401
Points : 434
Points : 434
Code perl :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
my $i = 0;
 
#ouvre fichier et compte les lignes
open FILE, "/tmp/file.txt";
while(<FILE>) {
    $i++;
}
 
# retour au debut
seek FILE, 0, SEEK_SET;
 
# autres operations necessaires
 
close FILE;
__________________
Mon wiki (on y parle Debian principalement) : http://www.tchetch.net/
Tchetch est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/09/2008, 16h11   #5
Expert Confirmé Sénior
 
Avatar de frp31
 
Homme francois
Ingénieur systèmes et réseaux
Inscription : juillet 2006
Messages : 3 546
Détails du profil
Informations personnelles :
Nom : Homme francois
Âge : 35
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur systèmes et réseaux
Secteur : Aéronautique - Marine - Espace - Armement

Informations forums :
Inscription : juillet 2006
Messages : 3 546
Points : 7 779
Points : 7 779
le plus simple tu random un n° de ligne

mais tu ne cherche que cette ligne !

Citation:
sed -e "'$numero'p" fichier
ou
sed -e "'$numeroligne'!d" fichier
pour(gnu sed)
c'est ce qui sera le plus rapide.
sur un fichier dump de 24Go ça prend 3 secondes 5 seulement pour des lignes de 21935055 caracteres en en plus là c'est en écrivant un fichier de sortie...


sur un fichier de 90000lignes de 512 caractères tu peux diviser par 4 au moins...je pense en tout cas ça vaut le coup de tester.


Citation:
appora/exports2 > time sed -e "450p" vbresd.dmp > /tmp/toto

real 0m0.65s
user 0m0.06s
sys 0m0.09s
/appora/exports2 > ls -lrt vbresd.dmp
-rw-rw-r-- 1 dbvbresd dba 4063232 Sep 9 18:01 vbresd.dmp

/appora/exports2 > time sed -e "450p" bbresd.dmp > /tmp/toto

real 0m3.57s
user 0m0.44s
sys 0m0.32s
/appora/exports2 > ls -lrt bbresd.dmp
-rw-rw-r-- 1 dbbbresd dba 23736320 Sep 9 18:01 bbresd.dmp
/appora/exports2 > wc -c /tmp/toto
21935055 /tmp/toto

voilà le test avec des lignes de moins de 128 caractères :
Citation:
/tmp > i=0
/tmp > while [ $i -lt 90000 ] ; do echo "ssssssssssssssssssssssssssssss[......]ssssssssssssssssssssssssssss\n" > toto ; i=$(($i + 1)) ; done
/tmp > wc -l toto
180000 toto
/tmp > time sed -e "450!d" toto


real 0m0.14s
user 0m0.12s
sys 0m0.03s
/tmp >
beaucoup plus rapide que je pensais même...
frp31 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/09/2008, 10h23   #6
Invité régulier
 
Inscription : juin 2007
Messages : 13
Détails du profil
Informations forums :
Inscription : juin 2007
Messages : 13
Points : 6
Points : 6
Bonjour,

Effectivement, avec

Code :
1
2
 
entree=`sed -e "$numEntree!d" ${fileEntree}`
les performances sont vraiment bien meilleures.

Et cela a le mérite d'être simple à mettre en place.

Décidément, il y aura toujours à apprendre avec sed ! (c'est bien dans les vieilles marmites que l'on fait les meilleures soupes !)

Merci a tous
david2109 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/09/2008, 11h19   #7
Expert Confirmé Sénior
 
Avatar de frp31
 
Homme francois
Ingénieur systèmes et réseaux
Inscription : juillet 2006
Messages : 3 546
Détails du profil
Informations personnelles :
Nom : Homme francois
Âge : 35
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur systèmes et réseaux
Secteur : Aéronautique - Marine - Espace - Armement

Informations forums :
Inscription : juillet 2006
Messages : 3 546
Points : 7 779
Points : 7 779
sed avec une belle regexp est une commande unique de traitement par lot,

au lieu de trois si tu fais un cat un head et un tail + les deux pipes soit 5 éléments ....

le choix est vite fait....
le gros inconveignant, c'est peu simple, en ça peut parfois manquer de souplesse...

des scripts sed de 40 lignes.... c'est quasi illisible même quand on connait pas si mal.....en cas de besoin de mise à jour il est plus simple de le réecrire completment que d'essayer de comprendre ce qu'on a fait y'a six moi...
frp31 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 05h29.


 
 
 
 
Partenaires

Hébergement Web