Joseph Tux
Opérateurs « .. » et « ... »

Traiter des fichiers par blocs de lignes.

mercredi 25 novembre 2009

Ce script ne fait rien d’autre que d’afficher ce qu’il fait, au fur et à mesure qu’il le fait ..

traiter plusieurs fichiers
   fractionnés en blocs ( séparés par une ligne vide )
       chaque ligne du bloc étant examinée à son tour

Il peut servir de base pour traiter les blocs, les lignes des blocs ..

Il illustre essentiellement l’utilisation de l’ opérateur d’intervalle « .. »

Le script

Le script en l’état v 1.03
encore à peine sortie du four.. à compléter, deboguer..

  1. #! /usr/bin/perl
  2. use warnings;
  3. use diagnostics;
  4. use strict;
  5. use Carp;    #pour remplacer "die" par "croak" et "warn" par "carp"
  6. use File::Glob qw(:globally :case);    # jocker du shell ligne de commande ? *
  7.  
  8. ## TRAITER LES FICHIERS PAR BLOCS DE LIGNES
  9. ## SÉPARÉS PAR DES LIGNES VIDES ( /^$/ )
  10. ## Les versions 1.x prennent une liste de fichiers en ligne de commande
  11. ## (avec "File::Glob" : recommandation de Damian Conway )
  12.  
  13. ## Les versions 0.x ne prenaient pas d'argument ( ils étaient imposés dans le programme )
  14. ## version 0.02 Afficher aussi le nombre de doublons PAR BLOC
  15. ## Modification de l'affichage
  16. ## version 0.01 Cannevas à 3 boucles imbriquées: fichiers−>blocs−>lignes
  17. ## Ici affichage global du nombre des doublons sélectionnés ( pas par bloc )
  18. ## (y a plus qu' à .. )
  19.  
  20. #### Référence bibliographique:
  21. #−−Perl en action 6.8 pp 209 sqq
  22. #−−
  23. #−−Utiliser les OPERATEURS D'INTERVALLE: .. ou ...
  24. #−−
  25. #−−# Traitement de chaque ligne
  26. #−−while (<>) {
  27. #−− if (/Motif_debut/ .. /Motif_fin/) {
  28. #−− #Chaque ligne entre les lignes comportant ces 2 motifs est traitée
  29. #−− }
  30. #−−} # FIN du traitement
  31. #−−
  32. #−−.. accepte que Motif_debut et Motif_fin soient sur la même ligne => ( reconnaissance: true )
  33. #−−... ne reconnait pas une telle ligne => ( non reconnaissance: false )
  34. #−−
  35. #−−
  36. #−−#"
  37. #−−Discussion
  38. #−−
  39. #−−.. ou ...
  40. #−−renvoient vrai à partir de la reconnaissance du 1er motif,
  41. #−− à chaque ligne suivante, jusqu'à la reconnaissance du 2e motif
  42.  
  43. #−−−−
  44. #Exemple: fichiers de listes de doublons à traiter ( par exemple, en faire des liens physiques )
  45. # avec "fdupes −r /un/chemin/"
  46. # il y a plusieurs fichiers: un par système de fichier ( pour faire des liens physiques ! )
  47.  
  48. #traiter une série de fichiers
  49.  
  50. my @fichiers_de_doublons = <@ARGV>;    # Syntaxe de File::Glob
  51.  
  52. # TODO IMPLIQUE LE TRAITEMENT D'ERREURS
  53. my $numero_fichier = 0;
  54. my $toutes_lignes;        # compte ( toutes ) les lignes par fichier
  55. my $blocs_retenus;        # compte les lignes (retenues) par fichier
  56. my $num_ligne_retenue;    # compte les lignes par fichier
  57. my $num_ligne_par_bloc;
  58. FICHIER:
  59. foreach my $fichier_de_doublons (@fichiers_de_doublons) {
  60.  
  61.     $num_ligne_retenue = 0;    #
  62.     $toutes_lignes     = 0;    # compte les lignes par fichier
  63.     $numero_fichier++;
  64.     $blocs_retenus = 0;        # compte les lignes (retenues) par fichier
  65.     print "Fichier N° $numero_fichier \t";    # DEBUG
  66.     print "$fichier_de_doublons\n";            # DEBUG
  67.     open FICHIER_DE_DOUBLONS, "<", $fichier_de_doublons
  68.         or croak("ouverture de $fichier_de_doublons impossible $!");
  69.  
  70. #extraire les blocs d'un fichier ( blocs séparés par une ligne blanche(=vide ) )
  71.  
  72. BLOCS:
  73.     while (<FICHIER_DE_DOUBLONS>) {
  74.         chomp;
  75.         $toutes_lignes++;
  76.         print "$toutes_lignes Lignes explorées:\t";    #DEBUG
  77.         print "$_ ";                                    #DEBUG
  78.         if ( /^$/ .. /^$/ ) {                           ## NOUVEAU BLOC
  79.  
  80.             #Chaque ligne entre les lignes vides est traitée
  81.             #traiter chaque ligne du bloc
  82.             $blocs_retenus++;
  83.             $num_ligne_par_bloc = 0;
  84.             print "Fin du bloc n° $blocs_retenus \n";    #DEBUG
  85.  
  86.         LIGNE:
  87.  
  88.             #Doit elle être la référence ?
  89.  
  90.             #si oui: Faire une copie sans accès écriture
  91.             # attention aux modif. involontaires avec les liens physiques !
  92.  
  93.             #Transformer les doublons en liens−physiques
  94.         }
  95.         else {
  96.  
  97. ## C'est ici que les lignes du bloc seront traitées !
  98.             #print "$_ \n"; # DEBUG
  99.             $num_ligne_retenue++;
  100.             $num_ligne_par_bloc++;
  101.  
  102.             # print "Ligne retenue: N° $num_ligne_retenue\n" ; #DE
  103.  
  104.             print "Ligne retenue: n° $num_ligne_par_bloc\n";    #DEBUG
  105.  
  106.         }    ## Fin de if
  107.     }    ## Fin de while BLOC
  108.     close FICHIER_DE_DOUBLONS;
  109.     print
  110.         "\n −> $num_ligne_retenue lignes retenues et $blocs_retenus blocs dans
  111.  
  112.  
  113. le fichier n° $numero_fichier; \n";    #DEBUG
  114.  
  115.     #print "Fin du fichier de doublons n° $numero_fichier\n\n"; #DEBUG
  116. }    ## Fin de foreach $fichier_de_doublons
  117.  
  118. print "FINI\n";    #DEBUG
  119. exit 1;

Télécharger

Opérateurs « bloc »

Si j’ai bien compris
 [1]
, /debut/ .. /fin/ permet d’isoler tout bloc qui commence par /debut/ et se termine par /fin/ , même si /debut/ = /fin/ , alors que /debut/ ... /fin/ ratera une marche, si la fin d’un bloc est aussi le début du bloc suivant ( cas où /debut/ = /fin/ ), et ne reconnaîtra plus qu’un bloc sur deux dans ce cas !

Mon script envisage des fichiers où chaque bloc est séparé du suivant par une (seule) ligne vide ( /^$/ ) qui est donc à la fois debut et fin.

File::Glob

Ce script utilise le module standard File::Glob, avec sa syntaxe < >.

Le script a été testé avec des noms de fichiers invraisemblables, des trous et des caractères de malade, et il est passé apparemment sans dommage ( contrairement à la commande wc qui a pleuré ! ) [2]

Résultat

résultat de la commande suivante :

time ./Extraire_un_bloc_de_lignes.1.03 "/home/tmp/test/fdupes-r*" | egrep "blocs dans le fichier"

-> 47418 lignes retenues et 11487 blocs dans le fichier n° 1;
-> 317182 lignes retenues et 13857 blocs dans le fichier n° 2;
-> 594 lignes retenues et 102 blocs dans le fichier n° 3;

real    0m3.973s
user    0m3.204s
sys     0m0.392s

[1Travaux pratiques autodidactiques, sans aucune garantie, qu’on se le dise !

[2avec 3 fichiers de doublons de : 27k, 5m, 38m


Accueil | Contact | Plan du site | | Statistiques du site | Visiteurs : 127 / 77125

Suivre la vie du site fr  Suivre la vie du site GNU, LINUX, BSD, LL  Suivre la vie du site AIDES GNU/LINUX  Suivre la vie du site PERL   ?

Site réalisé avec SPIP 3.1.6 + AHUNTSIC

Creative Commons License