Réorganisations de données dans un fichier en Perl

Fermé
débutPerl - 19 juil. 2015 à 23:03
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 - 24 juil. 2015 à 10:20
Bonjour,

Tout d'abord merci pour cet espace très utile qui m'a fourni de nombreuses solutions en perl. Cependant je suis encore débutant et face au problème suivant:
Je cherche à transformer un fichier.txt ayant ce format :
---------------------------

exemple1.flac # (durée exemple1 = 66 centièmes de secondes)
00:21:29,642
00:23:15,628

exemple2.flac #(durée exemple2 = 1 seconde et 016 centièmes)
00:29:26,812
00:35:43,056
00:44:37,231

..etc

-------------------------
au format suivant :
-------------------------

1289,642 1290,302 exemple1
1395,628 1396,288 exemple1

1766,811 1767,828 exemple2
2143,055 2144,072 exemple2
2391,496 2392,512 exemple2

-------------------------

Trois actions me pose donc problème :
- récupérer le contenu des lignes comprise entre deux ligne bien particulière tel exemple1.flac et exemple2.flac
- convertir le temps du format hh:mm:ss,fff au format ssss,fff
- réorganiser ces informations dans l'ordre voulu, soit: début fin étiquette

while (<$in>) {	# LIT et regarde si la fin du fichier est atteinte
	($ligne=$_);
	@listeCase = split(/\n/,$ligne);  
	foreach $case (@listeCase) {
		if (my @res = grep { $_ =~ /00\:(\d\d)\:(\d\d),(\d\d\d)/ } @listeCase) {
			print "$case\t exemple1\n";
			
		}

Ce morceau de code me permet d'afficher le contenu des lignes avec une étiquette mais pas de séparer les différente portions. (chaque ligne est étiquetée avec exemple1 indifféremment)

Pour la conversion, je suis arrivé à ce code :
if ($temps=~/00\:(\d\d)\:(\d\d),(\d\d\d)/) {
	my $minute = $1;
	my $seconde = $2;
	my $centieme = $3;
	
	my $min = (($minute * 60) + $seconde);
	
	print "minutes : $min,$centieme \n";
}

Mais il ne convient pas tout à fait...

Je serais extrêmement reconnaissant pour toute aide !!! Merci

A voir également:

1 réponse

[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié par [Dal] le 20/07/2015 à 11:40
Dia duit débutPerl,

Si je ne me trompe pas, dans le format de résultat, la ligne "1289,642 1290,302 exemple1" est formée en :

- convertissant "00:21:29,642" en secondes et millièmes, et en affichant cela, soit "1289,642"
- en ajoutant à cette valeur 66 centièmes de secondes, et en affichant cela, soit "1290,302", cette valeur de 66 centièmes semblant provenir de la première ligne du bloc "exemple1.flac # (durée exemple1 = 66 centièmes de secondes)"
- en affichant "exemple1.flac", cette chaîne semblant provenir de la même première ligne "exemple1.flac # (durée exemple1 = 66 centièmes de secondes)"

Tu n'as pas du tout expliqué ce qui est en gras.

Comment sais-tu quelle valeur ajouter pour obtenir le 2nd chiffre ?
Dois-tu le dériver du texte libre mis en commentaire ?

Dans ton exemple, le texte affiché en commentaire sur la durée a un format variable selon que la durée dure plus ou moins d'une seconde :

"exemple1.flac   # (durée exemple1 = 66 centièmes de secondes)"
"exemple2.flac #(durée exemple2 = 1 seconde et 016 centièmes)"

quel est le format s'il y a au moins deux secondes ?
quel est le format s'il y a plus de 60 secondes ?
quel est le format s'il y a plus de 60 minutes ?
(etc. jours, mois,... on peut aller loin comme çà)
les temps d'origine sont en heures, minutes, secondes et millièmes de secondes. Dans le temps a ajouter, peut-il y avoir des millièmes aussi ? Si oui, les centièmes sont-ils alors aussi mentionnés ou la mention des millièmes remplace-t-elle celle des centièmes ?

Par curiosité, d'où vient ce fichier et c'est pour quoi faire ?


Dal
0
Merci pour votre réponse Dal, vous avez raison je n'avais pas suffisament expliqué cette partie, et il s'agit bien des millièmes (mea culpa). Ce fichier à pour objectif d'être utilisé pour l'annotation de fichier audio, avec le temps de début, le temps de fin, et l'étiquette de l'occurence.

Pour l'instant je ne dispose que du temps de début, mais ai accès à la durée de chaque occurence.

La partie qui me pose le plus de problème est dans le découpage. Je sens théoriquement que je devrait me servir d'un tableau de hachage pour stocker chaque information. Mais la syntaxe exacte m'échappe. (entre autres chose) Avez vous une idée la dessus qui me permettrais d'afficher :
---------------------
1289,642 exemple1
1395,628 exemple1

1766,811 exemple2
2143,055 exemple2
---------------------
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
20 juil. 2015 à 17:18
Salut, sur ton jeu de données, un code comme celui-ci :

#!/usr/bin/perl

use strict;
use warnings;

my $nom_bloc = "";

while (<DATA>) {
    # si ligne blanche, $nom_bloc est réinitialisé et on saute 
    # une ligne
    if (/^\s*$/) {
        $nom_bloc = "";
        print "\n";
    } elsif
    # si nouveau bloc, conserver le nom dans $nom_bloc
    (/^(exemple\d+)\.flac\s+#\s*\(durée\s(exemple\d+)\s*=\s*/) {
        # vérifier que $1 et $2 sont égaux
        if ($1 eq $2) {
            $nom_bloc = $1;
        } else {
            print "Erreur de format ligne $_\n";
            exit;
        }
    } elsif
    # si temps, capturer, convertir et afficher
    (/^(\d+):(\d+):(\d+),(\d+)$/) {
        # si $nom_bloc est vide, c'est qu'il y a une 
        # erreur de format
        if ($nom_bloc eq "") {
            print "Erreur de format ligne $_, aucun bloc identifiable\n";
            exit;
        }
        # $1 à $4 ont respectivement, heure, minutes, 
        # secondes et millièmes
        print int(($1 * 3600) + ($2 * 60) + $3) .
            ",$4 $nom_bloc \n";
    }
    # si c'est autre chose, le format est incorrect
    else {                                                                                              
        print "Erreur de format ligne $_, format non identifié\n";
        exit;
    }
}

__DATA__
exemple1.flac   # (durée exemple1 = 66 centièmes de secondes)
00:21:29,642
00:23:15,628

exemple2.flac  #(durée exemple2 = 1 seconde et 016 centièmes)
00:29:26,812
00:35:43,056
00:44:37,231

donne ceci :

1289,642 exemple1 
1395,628 exemple1

1766,812 exemple2
2143,056 exemple2
2677,231 exemple2


Dal
0
débutPerl > [Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024
20 juil. 2015 à 19:03
Merci beaucoup ! Ce code fonctionne en effet!
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
24 juil. 2015 à 10:20
Le code est abondamment commenté et fait la gestion d'erreurs de format aussi, autrement il pourrait tenir en une dizaine de lignes.

Ce sont les regexp qui font tout le travail, l'ordre séquentiel de lecture étant suffisant pour faire ce que tu veux faire.
0