Retourner aux forums || Retourner au forum Programmation.perl
Programmation.perl : parser un gros fichier
Posté par Nicolas Boulay () le 15 octobre 2004Je le lis avec read par bloc. Mon problème est que un motif peut être à cheval sur 2 blocs. Je penssais utiliser une sorte de fifo de taille double du buffer pour faire ça. Mais je me demande si il n'y a pas de manière plus "idiomatique".
> Lire le message (14 commentaires, moyenne: 1,6).
meuh
-
[^]Re: meuh
Posté par Nicolas Boulay () le 15/10/2004 à 08:56. (lien). Évalué à 1.ben une manière plus perlienne, quoi.
Le type de code que l'on retrouverait dans un programme d'un bon codeur perl.
J'ai un peu peur en fait que lancer une regex sur une fifo de taille double soit un peu lent :/-
[^]Re: meuh
Posté par gc (page perso, ) le 15/10/2004 à 10:10. (lien). Évalué à 3.bah. moi je ferais :
open F, '</tmp/track01.cdda.wav' or die "open: $!\n";
my ($buf, $prev);
while (1) {
my $ret = read F, $buf, 4096;
if (!defined($ret)) {
die "read: $!\n"
} elsif (!$ret) {
last;
} else {
if ("$prev$buf" =~ /(gc\w\w)/) {
print "match: $1\n";
}
$prev = $buf;
}
}
mais y'a sûrement pire.-
[^]Re: meuh
Posté par Nicolas Boulay () le 15/10/2004 à 11:12. (lien). Évalué à 1.Je fais :
my $bufferbin; my $oldbufferbin = ""; while (read FICHIER, $bufferbin, 4*1024){ my $fifo = $oldbufferbin.$bufferbin; while ($fifo =~ /(\x1A\xCF\xFC\x1D.{2000,2100})\x1A\xCF\xFC\x1D/g){ my $cadu = $1; blablabla .... } $oldbufferbin = $bufferbin; }cela ressemble beaucoup à ton code. j'ai un problème par contre sur le while (/../g), j'ai un début de trame marqué par le code. Donc la fin de la trame est donné par le début de la trame suivante. Mais si j'utilise la regex d'en haut, la boucle suivante ne va pas matcher le début de la trame (qui la fin de la précédente). Il faudrait lui dire de revenir en arrière. Mais je n'ai pas encore trouvé comment.-
[^]Re: meuh
Posté par Nicolas Boulay () le 15/10/2004 à 11:38. (lien). Évalué à 1.En fait, ça marche (presque) avec :
/(\x1A\xCF\xFC\x1D(.|\x00){2000,2100})(?=\x1A\xCF\xFC\x1D)/
Le truc c'est (?=...) qui n'est pas pris en compte dans le déplacement.-
[^]Re: meuh
Posté par Nicolas Boulay () le 15/10/2004 à 13:27. (lien). Évalué à 1.bon en fait cela ne marche pas du tout.
J'ai l'impression qu'il match toujours la même trame :(
il doit y avoir un soucis avec la définition du "while (//g)"
-
-
-
-
Une solution...
Un truc comme ca ?
my ($buffer, $chunk);
my $SEPARATOR = 'X'; # C'est ton séparateur de motifs
while (read F, $chunk, 4096)
{
die "Read problem" if not defined $chunk;
last if not $chunk;
$buffer .= $chunk;
if ($buffer =~ s/^([^SEPARATOR]*)$SEPARATOR//)
{
ProcessOneFrame ($1);
}
}
die "Incomplete Frame ??" if $buffer;
P.S. il faut faire le même genre de choses pour les paquets IP fragmentés, ils peuvent arriver en plusieurs fois, et il faut donc "recoller les morceaux"
P.P.S code pas testé
-
[^]Re: Une solution...
Posté par Nicolas Boulay () le 15/10/2004 à 11:20. (lien). Évalué à 1." $buffer .= $chunk;" <- pas bon ça !
à la fin buffer fait une taille énorme.
j'ai toujours mon pb de relecture pour les 2ième passes :/-
[^]Re: Une solution...
Posté par Olivier Macchioni () le 15/10/2004 à 11:22. (lien). Évalué à 2.Oui, mais il se vide chaque fois qu'il peut :
$buffer =~ s/^([^SEPARATOR]*)$SEPARATOR//
(qu'on pourrait d'ailleurs avantageusement remplacer par :
while ($buffer =~ s/^([^SEPARATOR]*)$SEPARATOR//)
{
ProcessOneFrame ($1);
}-
[^]Re: Une solution...
Posté par Nicolas Boulay () le 15/10/2004 à 11:34. (lien). Évalué à 1.à oui, j'avais pas vu.
c'est pas plutôt : "s/^([^SEPARATOR].*)$SEPARATOR//)" et c'est vrai que cela à l'avantage de bien réduire la taille buffer et d'aller plus vite j'imagine.
-
-
-
[^]Re: Une solution...
Posté par Nicolas Boulay () le 15/10/2004 à 13:41. (lien). Évalué à 1.Pourrais-tu détailler la regexp que tu utilises, pourquoi une variable pourquoi 2x "^" pourquoi les '[]' etc..
-
[^]Re: Une solution...
Posté par Olivier Macchioni () le 15/10/2004 à 14:49. (lien). Évalué à 3.Oulala, vaste question...
Le premier ^ spécifie "Début de chaine"
Les [] veulent dire "Un des caractères parmi... et le ^ dans les [] effectue une négation, donc "aucun des caractères parmi".
De façons plus générale, il est difficile (et inutile) d'expliquer ce que sont les regexp et comment elles fonctionnent dans un forum... Plutôt te renvoyer vers quelques sources d'information :
- perldoc perlrequick ou perldoc perlretut ou perldoc perlre ou encore perldoc perlreref (il faut avoir installé le package de documentation Perl qui va bien)
- l'excellent livre consacré aux regexp de chez O'Reilly http://www.oreilly.com/catalog/regex/(...)
- google
- et le sympatique Vrex qui a tout pour plaire à un débutant : http://page.sourceforge.net/vrex.html(...)
Bon courage ! (et comment as-tu pu vivre sans elles ?)-
[^]Re: Une solution...
Posté par Nicolas Boulay () le 15/10/2004 à 14:56. (lien). Évalué à 2.Je connais les regexp, je ne savais pas que "^" signifiait une négation, je croyais que cela voulais dire une nouvelle fois "début de fichier". Ce qui m'embrouillais sur le reste
-
[^]Re: Une solution...
Posté par Nicolas Boulay () le 18/10/2004 à 11:55. (lien). Évalué à 1.Bon, j'ai eu quelques soucis en plus.
Mon délimiteur fait plusieurs caractère de long donc le "truc" [^abc] ne marche pas. Ensuite, je parse du binaire et "." ne peut pas prendre certaine valeur notement "\n", il faut rajouter /s pour cela.
Donc ma regexp est devenu :
s/(\x1a\xcf\xfc\x1d.{2000,2100})((?=\x1a\xcf\xfc\x1d)|$)//s
(?=) pour la présence du délimiteur à la fin
/s pour ne pas se faire avoir avec '.'
vala merci pour l'aide !
-
-
-
Revenir en haut de page || Retourner aux forums || Retourner au forum Programmation.perl



Cette discussion est archivée, il n'est plus possible de laisser des commentaires.
Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.