Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1501 connectés 

  FORUM HardWare.fr
  Programmation
  Shell/Batch

  Aide:extraire un groupe de données depuis un groupe de fichiers

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Aide:extraire un groupe de données depuis un groupe de fichiers

n°2250314
scientista
i'll sleep when I'm dead
Posté le 07-02-2015 à 14:01:26  profilanswer
 

Bonjour, ceci est mon premier post, alors bonjour a tous :)
 
je m'inscrit seulement maintenant parce que j'ai un probleme de progammation en BAT. ( level : newbie, recherche sur internet de script deja ecrite que je bricole)
 
Je cherche a extraire la meme info (heure), dans une serie de fichiers qui ont le meme nom  
 
Je bosse dans la science et mes données sont toutes données sous la formes d'un dossier (*.RAW), qui contient un ensemble de fichier.
 
->  dossier " Data"
 
--> dossier " monexperience01.RAW "  
---> fichier " _CHRO001.DAT "
---> fichier " _CHRO002.DAT "
       .
       .
---> fichier "_HEADER.TXT"
 
--> dossier " monexperience02.RAW "  
---> fichier " _CHRO001.DAT "
---> fichier " _CHRO002.DAT "
       .
       .
---> fichier "_HEADER.TXT"
 
 
 
 
chaque fichier   " _HEADER.TXT " commence par
 
$$ Version: 01.00
$$ Acquired Name: 20150206_QC_01
$$ Acquired Date: 06-Feb-2015
$$ Acquired Time: 13:34:44
$$ Job Code: 20150206_HEP
$$ Task Code:  
$$ User Name:  
 
 
 
Donc, j'essaie de programmer un BAT, qui me fait un outpout   "temps.log"  ayant dedans une liste de la variable " $$ Acquired Time: " pour chaque fichier " _HEADER.TXT "
 
en ouvrant le fichier " temps.log " j aimerai voir
 
"
13:34:44
13:49:46
14:04:42
14:19:48
 .
 .
 .
               "
 
le problem: ca marche pas, ca me renvoie toutes les infos
 
est ce que quelqu'un peux me corriger??? [:dark_schneider]  
 
vopic mon BAT
 
@echo off
(
for /f " skip=3 tokens=1,2 delims=" %%a in ('dir *.txt /a:-d /b /s') do (
 
   for /f " usebackq tokens=1,2 delims==" %%a in ("%%a" ) do (
      if not defined skip set /p "=%%a,"<nul
      if "%%a"=="$$ Acquired Time:" set skip=3
   )
 echo(
 )
)>"temps.txt"


Message édité par scientista le 07-02-2015 à 21:32:44
mood
Publicité
Posté le 07-02-2015 à 14:01:26  profilanswer
 

n°2250329
scientista
i'll sleep when I'm dead
Posté le 07-02-2015 à 20:52:20  profilanswer
 

hum, j ai trouvé une autre approche, mais ca ne marche que dans un seul dossier.
 
(ca donne le string complet " $$ Acquired Time: 15:13:10 " :/ mais bon c'est deja mieux que rien)
 
  :hello:  est ce que quelqu'un peux m'aider pour modifier ce code pour que ca extrait ce string pour chaque dossier?
 
 

Code :
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set InputFile=_HEADER.TXT
  4. set OutputFile=temps.txt
  5. for /f "skip=3 delims=" %%d in ('type "%InputFile%"') do (set FirstLine=%%d&goto LastLines)
  6. :LastLines
  7. set CsvLine=
  8. for /f "skip=3 tokens=1* delims=:" %%a in ('type "%InputFile%"') do (
  9. call :Trim %%f
  10. )
  11. >>"%OutputFile%" echo %FirstLine%
  12. ECHO del "%InputFile%"
  13. goto :eof
  14. :Trim
  15. set Value=%*
  16. goto :eof

n°2250467
scientista
i'll sleep when I'm dead
Posté le 09-02-2015 à 23:43:27  profilanswer
 

Merci Beaucoup Phoenix :)  
 
J'ai essayé les deux scripts, et aucun des deux ne renvoient de données du tout malheureusement.
 
 je vois que le script ce lance, mais le fichier output ne se crée pas.
 
Comment veux tu que je le teste?

n°2250639
scientista
i'll sleep when I'm dead
Posté le 11-02-2015 à 21:37:49  profilanswer
 

Je bosse dans la science en spectrometry de masse.  
J ai un patch qui me permet de recalibrer entre deux echantillions, mais ce process peut prendre plus au moins de temps.
Chaque echantillion  a  "l'heure" ou il commence dans ce fichier _Header.txt, donc pour pouvoir calculer le "temps moyen" que prend un echantillion je doit extraire manuellement cette heure,  les mettre dans excel... ( je fait 96 echantillions par 24 heures, faire tout ca a la main après je suis  :pt1cable: )  
 
j'ai bidoullé dans tous les sens ce que tu m'as donné ca marche pas :/
J'ai essayé une autre approche, en utilisant le vba dans excel, mais la autres probleme: je n'arrive pas a extraire a partir d'un fichier qui a le meme nom situé dans different dossier :/
 
J'ai cherhé aussi pour un logiciel qui pourrai me permettre de faire ca, aucun ne me le perme ( avec un logiciel comme textcrawler , tu peux faire que des find and replace, pas moyen de faire n find puis metre ca dans un ouput :/
 
 

n°2250652
gilou
Modérateur
Modzilla
Posté le 12-02-2015 à 04:09:17  profilanswer
 

Pourquoi ne pas faire ça avec un langage de script comme perl ou python?
Ce sont des langages particulièrement adaptés à ce genre de choses.
 

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use autodie;
  5.  
  6. use File::Grep qw(fgrep);
  7. use File::Glob qw(bsd_glob);
  8.  
  9. # deux valeurs arbitraires pour tester a adapter à ses besoins
  10. my $datareg = 'C:/Perl/test/Data/*.RAW/_HEADER.TXT';
  11. my $datalog = 'C:/TMP/log.txt';
  12.  
  13. # la regexp identifiant la ligne dans le fichier
  14. my $pattern = qr("\$\$ Acquired Time: " );
  15.  
  16. my @times;
  17. my @matches = fgrep {/^$pattern/} bsd_glob("$datareg" );
  18. # en sortie @matches est une liste de structures avec le nom du fichier, le nb de ligne matchées dans le fichier
  19. # et un hash (numéro de ligne, ligne), pour chaque ligne matchée
  20.  
  21. # cuisine pour récupérer les valeurs qui nous intéressent et les ranger dans @times
  22. foreach my $match (@matches) {
  23.  if ($match->{'count'} == 1) {
  24.    $_ = ((values %{$match->{'matches'}})[0]);
  25.    chop;
  26.    s/^$pattern//;
  27.    push @times, $_;
  28.  }
  29. }
  30.  
  31. #écriture de @times dans le fichier de log
  32. open my $fh, '>>', $datalog;
  33. foreach (@times) {
  34.  print $fh $_,"\n";
  35. }
  36. close $fh;


 
A+,


Message édité par gilou le 12-02-2015 à 04:09:47

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2250763
scientista
i'll sleep when I'm dead
Posté le 12-02-2015 à 23:18:00  profilanswer
 

Bonsoir Gilou et merci,
 
je n'ai aucune connaissance en Perl  :sweat: , j 'ai donc installé Perl Active.
 
A la premiere execution de ton code, j'ai eu un message d'erreur, me demandant fgrep.
 J'ai donc utilise ppm, et ai installé File-Grep v 0.02(find matches to a pattern in a series of files and related functions).
 
Second execution du code, le  fichier log.tct se crée mais il est vide :(
 
j'ai essayé d'installer  File-MultineGrep v0.01 (Match multiple line block delimited by a star/stop pattern) (meme si je ne vois pas de stop pattern dans ton code).
 
Nouvel essaie, fichier log.txt vide.  
 
J ai assayé App-file-Grepper v0.06 (greps file for pattern).
nouvel essaie, fichier log.txt vide .
 
Pour le glob, j'ai deja d'installé Text-glob v0.09 (match globing patterns against text).
 
Ne connaissant pas du tout ce language, je n'arrive pas a voir ou ca pourrait buger :/
 
J'ai uploader ici le "dossier type" de données que ma machine me sort (en version allege, avec seulement le fichier _Header.TXT).
 
Peux tu essayer ton script sur ton pc pour voir si ca vien de mon install de Perl?
 
http://cjoint.com/?0Bmxz4S4758
 
Merci :)  

n°2250766
gilou
Modérateur
Modzilla
Posté le 13-02-2015 à 00:51:17  profilanswer
 

Bonsoir,
1) Tu as installé Active Perl
2) Avec ppm, tu as installé File-Grep
A priori, tu n'as pas besoin de plus.
 
J'ai testé le zip et ça marchait pas pour moi non plus (bizarre, hier ça marchait dans mes tests) mais je sais pourquoi.
Remplaces  
my $pattern = qr("\$\$ Acquired Time:" );
par
my $pattern = qr(\$\$ Acquired Time: );
donc plus de doubles quotes autour, et ça règle le problème.
 
Pour savoir comment j'ai débuggé:
J'ai ajouté après le use autodie; une ligne
use Data::Dumper;
 
et après le my @matches = fgrep {/^$pattern/} bsd_glob("$datareg" );
j'ai ajouté une ligne
print Dumper(@matches)
 
ce qui m'a donné a l'exécution un écran avec

$VAR1 = {
          'count' => 0,
          'matches' => {},
          'filename' => 'C:/TOF01.PRO/Data/TEST_Pos_s10w2.raw/_HEADER.TXT'
        };
$VAR2 = {
          'count' => 0,
          'matches' => {},
          'filename' => 'C:/TOF01.PRO/Data/TEST_Pos_s1w2.raw/_HEADER.TXT'
        };
$VAR3 = {
          'count' => 0,
          'matches' => {},
          'filename' => 'C:/TOF01.PRO/Data/TEST_Pos_s1w3.raw/_HEADER.TXT'
        };
$VAR4 = {
          'count' => 0,
          'matches' => {},
          'filename' => 'C:/TOF01.PRO/Data/TEST_Pos_s8w5.raw/_HEADER.TXT'
        };


filename montre que les fichiers étaient trouvés, mais count a 0 montre que le pattern n'était pas trouvé dans le fichier. J'ai modifié le pattern en réfléchissant un peu et j'ai ensuite obtenu ce qu'il fallait:

$VAR1 = {
          'count' => 1,
          'matches' => {
                         '4' => '$$ Acquired Time: 15:30:16
'
                       },
          'filename' => 'C:/TOF01.PRO/Data/TEST_Pos_s10w2.raw/_HEADER.TXT'
        };
$VAR2 = {
          'count' => 1,
          'matches' => {
                         '4' => '$$ Acquired Time: 15:13:10
'
                       },
          'filename' => 'C:/TOF01.PRO/Data/TEST_Pos_s1w2.raw/_HEADER.TXT'
        };
$VAR3 = {
          'count' => 1,
          'matches' => {
                         '4' => '$$ Acquired Time: 15:18:51
'
                       },
          'filename' => 'C:/TOF01.PRO/Data/TEST_Pos_s1w3.raw/_HEADER.TXT'
        };
$VAR4 = {
          'count' => 1,
          'matches' => {
                         '4' => '$$ Acquired Time: 15:24:32
'
                       },
          'filename' => 'C:/TOF01.PRO/Data/TEST_Pos_s8w5.raw/_HEADER.TXT'
        };


 
Tant que j'y suis je t'explique la suite:
On a dans @matches une liste de 4 structures un peu complexe
foreach my $match (@matches) {
...
}
je parcours la liste mon élément courant est représenté par la variable $match
 if ($match->{'count'} == 1) {
...
 }
match est une référence sur un hash (une liste de (clé, valeur) les clés étant uniques) de clés count, matches et filename.
avec $match->{'count'} j'accède a la valeur du hash pour la clé count
Je filtre pour les éléments ayant cette valeur a 1 (ie le pattern a été trouvé une fois dans le fichier)
$_ = ((values %{$match->{'matches'}})[0]);
maintenant je m'intéresse a la valeur du hash pour la clé matches. La valeur est a nouveau une référence sur un hash, dont les clés sont les numéros des lignes avec le pattern, et les valeurs les contenus desdites lignes.
Je sais qu'il n'y a qu'une ligne, je veux la récupérer, mais je ne connais pas son numéro de ligne.
%{$match->{'matches'}} déréférence la référence a un hash, et est donc le hash lui même
(values %{$match->{'matches'}}) est la liste des valeurs de ce hash
(values %{$match->{'matches'}})[0] est le premier élément de cette liste (et je sais que c'est le seul).
$_ = ((values %{$match->{'matches'}})[0]); copie cet élément (ie le texte de la ligne qui matche le pattern) dans la variable scalaire par défaut $_
chop vire le \n final d'une ligne, comme il est sans argument, il s'applique à la variable scalaire par défaut $_
s/^$pattern//; élimine le pattern en début de ligne de la variable scalaire par défaut $_
$_ contient maintenant le texte de la ligne sans le pattern initial ni le \n final
push @times, $_;
Je range ce texte dans la liste @times.
EDIT: faut aussi changer le open my $fh, '>>', $datalog; par open my $fh, '>', $datalog; (avec >>, c'est en mode append)
A+,


Message édité par gilou le 13-02-2015 à 16:00:03

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2250807
gilou
Modérateur
Modzilla
Posté le 13-02-2015 à 16:05:05  profilanswer
 

Et une autre version, un peu plus pédagogique:
On fait pratiquement tout soi même ici, plutôt que de le laisser faire par des modules (sauf le parcours récursif de répertoire, qui utilise un module standard).
Comme on n'a pas de structures de données complexes, c'est plus lisible pour un débutant en perl.
 

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use autodie;
  5. use File::Find;
  6.  
  7. # deux valeurs arbitraires pour tester a adapter à ses besoins
  8. my $startdir = 'C:/TOF01.PRO';
  9. my $datalog = "$startdir/log.txt";
  10.  
  11. # la regexp identifiant la ligne dans le fichier
  12. my $pattern = qr(\$\$ Acquired Time:);
  13. my @times;  # cette globale est utilisée dans wanted, et doit être définie avant
  14.  
  15. # on parcourt récursivement les répertoires et
  16. # on appelle wanted a chaque fichier ou répertoire rencontré
  17. find(\&wanted, "$startdir/Data" );
  18. # après le parcours, écriture des contenus trouvés et rangés dans @times dans le fichier de log
  19. open my $fh, '>', $datalog;
  20. foreach (@times) {
  21.  print $fh $_,"\n";
  22. }
  23. close $fh;
  24.  
  25.  
  26. sub wanted {
  27.  # $_ contient le nom du fichier ou répertoire
  28.  # et le directory de travail est positionné dans celui actuellement parcouru
  29.  # ce qui fait que open marchera avec juste le nom du fichier, sans path
  30.  
  31.  # directory
  32.  if (-d) {
  33.    # process initial directory
  34.    return if (/^\.$/o);  # on pourrait faire if ( $_ eq "." ) mais j'aime mieux les expressions régulières
  35.    # return, car on ne fait pas de traitement spécifique au répertoire lui même
  36.    # mais on parcourt quand même les fichiers et répertoires qu'il contient
  37.    # process .raw directories
  38.    return if (/^.*\.raw$/io);  # /i donc case insensitive, ça marchera aussi avec xxx.RAW
  39.    # skip others directories
  40.    $File::Find::prune = 1;
  41.  }
  42.  
  43.  # files
  44.  if (-f) {
  45.    # skip file unless it is _HEADER.TXT
  46.    return unless (/^_HEADER.TXT$/o);
  47.    # on ouvre le fichier
  48.    open my $fh, "<", $_;
  49.    while (<$fh> ) {
  50.      # on supprime le \n final
  51.      chop;
  52.      # on cherche la ligne
  53.      if (/^$pattern\s+(\d{2}:\d{2}:\d{2})\s*$/o) {
  54.        # on s'est arrangé avec les parenthèses pour mettre le contenu qui nous intéresse dans le 1er groupe, $1
  55.        # on le range dans @times
  56.         push @times, $1;
  57.        # inutile de continuer à lire le fichier
  58.         last;
  59.      }
  60.    }
  61.    close $fh;
  62.  }
  63.  return;
  64. }


 
A+,


Message édité par gilou le 13-02-2015 à 16:42:49

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2250820
gilou
Modérateur
Modzilla
Posté le 13-02-2015 à 17:50:36  profilanswer
 

Et encore une version pédagogique qui ne fait appel à aucun module particulier.
Elle suppose juste que les répertoires en .raw sont tous dans le répertoire Data
 

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use autodie;
  5.  
  6. # deux valeurs arbitraires pour tester a adapter à ses besoins
  7. my $startdir = 'C:/TOF01.PRO';
  8. my $datalog = "$startdir/log.txt";
  9. # la regexp identifiant la ligne dans le fichier
  10. my $pattern = qr(\$\$ Acquired Time:);
  11.  
  12. my (@dirs, @files, @times);
  13. opendir(my $dh, "$startdir/Data" );
  14. # On récupère les sous répertoires de Data en .raw
  15. @dirs = grep /.\.raw$/io, readdir($dh);
  16. closedir($dh);
  17. # on y cherche les fichiers en _HEADER.TXT
  18. foreach my $dir (@dirs) {
  19.  opendir(my $dh, "$startdir/Data/$dir" );
  20.  push @files, map {"$startdir/Data/$dir/$_"} grep /^_HEADER.TXT$/o, readdir($dh);
  21.  closedir($dh);
  22. }
  23. # on y cherche les lignes avec le pattern, et si trouvé,
  24. # on stocke la partie de la ligne en d{2}:\d{2}:\d{2} dans @times s'il y en a une
  25. foreach my $file (@files) {
  26.  open(my $fh, $file);
  27.  push @times, grep defined, map {m/\s(\d{2}:\d{2}:\d{2})\s*$/; $1} grep /^\s*$pattern/, (<$fh> );
  28.  close($fh);
  29. }
  30. # écriture du contenu de  @times dans le fichier de log
  31. open my $fh, '>', $datalog;
  32. foreach (@times) {
  33.  print $fh $_,"\n";
  34. }
  35. close $fh;


Un des principes de perl, c'est qu'il n'y a pas UNE bonne méthode pour faire les choses, mais des méthodes adaptées au niveau de celui qui utilise le script, l'important étant que le script fasse ce qui est voulu.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2251082
scientista
i'll sleep when I'm dead
Posté le 18-02-2015 à 00:32:17  profilanswer
 

:bounce:  :)  Merci Gilou !!!!!!!!!!!  :love:  
J 'ai testé le premier script que tu as posté et ca marche !!!!!!
 
Merci beaucoup pour le temps que tu as passé pour l'ecrire.
 
Je comprends en lisant les deux autres script qu'effectivement il y a beaucoup de " facon d'ecrire" :)
 
Je vais essayer de modifier le3 eme script , pour faire deux recherches sur le meme fichier et separer par un point virgule ( ou un tab), afin de pouvoir utiliser le fichier dans excel.
 
PERL est mon nouvel ami :)
 
Gilou est ce que tu connais un bon site pour apprendre le PERL?
(MERCI ENCORE)

mood
Publicité
Posté le 18-02-2015 à 00:32:17  profilanswer
 

n°2251126
gilou
Modérateur
Modzilla
Posté le 18-02-2015 à 12:31:31  profilanswer
 

Pour écrire au directement au format Excel, il y a le module Excel::Writer::XLSX, ou bien Text::CSV si on veut écrire au format csv.
 
Il y a pas mal de tutoriels perl plus ou moins bon.
Sur cette page: http://qntm.org/files/perl/perl.html se trouve résumé l'essentiel de ce qu'il y a à savoir sur le langage. Et c'est bien mieux fait que sur pas mal de sites.
Cet article http://matt.might.net/articles/perl-by-example/ est bien aussi.
 
Ensuite, une bonne méthode est de chercher sur le web des exemples proche de ce qu'on veut faire (google "perl ..." et filtrer les retours sur Perl Monks ou StackOverflow), les comprendre et les adapter a son cas.
 
A+,
 
 
 


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Shell/Batch

  Aide:extraire un groupe de données depuis un groupe de fichiers

 

Sujets relatifs
[JAVA] Parser un fichier de log sans le lockerDéplacement fichier
Suppression de fichierouvrir un fichier texte en java
Traiter un fichier xmlSuppression d'un fichier en lecture seule
Importer valeurs depuis un fichier texte dans des variables VBSParser un fichier.txt en PHP
parser un fichier xml[RESOLU] [POWERSHELL] Modifier des lignes précises sur un fichier
Plus de sujets relatifs à : Aide:extraire un groupe de données depuis un groupe de fichiers


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR