Traiter des fichiers par blocs de lignes.
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 tourIl 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
#! /usr/bin/perl
use warnings;
use diagnostics;
use strict;
use Carp; #pour remplacer "die" par "croak" et "warn" par "carp"
use File::Glob qw(:globally :case); # jocker du shell ligne de commande ? *
## TRAITER LES FICHIERS PAR BLOCS DE LIGNES
## SÉPARÉS PAR DES LIGNES VIDES ( /^$/ )
## Les versions 1.x prennent une liste de fichiers en ligne de commande
## (avec "File::Glob" : recommandation de Damian Conway )
## Les versions 0.x ne prenaient pas d'argument ( ils étaient imposés dans le programme )
## version 0.02 Afficher aussi le nombre de doublons PAR BLOC
## Modification de l'affichage
## version 0.01 Cannevas à 3 boucles imbriquées: fichiers−>blocs−>lignes
## Ici affichage global du nombre des doublons sélectionnés ( pas par bloc )
## (y a plus qu' à .. )
#### Référence bibliographique:
#−−Perl en action 6.8 pp 209 sqq
#−−
#−−Utiliser les OPERATEURS D'INTERVALLE: .. ou ...
#−−
#−−# Traitement de chaque ligne
#−−while (<>) {
#−− if (/Motif_debut/ .. /Motif_fin/) {
#−− #Chaque ligne entre les lignes comportant ces 2 motifs est traitée
#−− }
#−−} # FIN du traitement
#−−
#−−.. accepte que Motif_debut et Motif_fin soient sur la même ligne => ( reconnaissance: true )
#−−... ne reconnait pas une telle ligne => ( non reconnaissance: false )
#−−
#−−
#−−#"
#−−Discussion
#−−
#−−.. ou ...
#−−renvoient vrai à partir de la reconnaissance du 1er motif,
#−− à chaque ligne suivante, jusqu'à la reconnaissance du 2e motif
#−−−−
#Exemple: fichiers de listes de doublons à traiter ( par exemple, en faire des liens physiques )
# avec "fdupes −r /un/chemin/"
# il y a plusieurs fichiers: un par système de fichier ( pour faire des liens physiques ! )
#traiter une série de fichiers
my @fichiers_de_doublons = <@ARGV>; # Syntaxe de File::Glob
# TODO IMPLIQUE LE TRAITEMENT D'ERREURS
my $numero_fichier = 0;
my $toutes_lignes; # compte ( toutes ) les lignes par fichier
my $blocs_retenus; # compte les lignes (retenues) par fichier
my $num_ligne_retenue; # compte les lignes par fichier
my $num_ligne_par_bloc;
FICHIER:
foreach my $fichier_de_doublons (@fichiers_de_doublons) {
$num_ligne_retenue = 0; #
$toutes_lignes = 0; # compte les lignes par fichier
$numero_fichier++;
$blocs_retenus = 0; # compte les lignes (retenues) par fichier
print "Fichier N° $numero_fichier \t"; # DEBUG
print "$fichier_de_doublons\n"; # DEBUG
open FICHIER_DE_DOUBLONS, "<", $fichier_de_doublons
or croak("ouverture de $fichier_de_doublons impossible $!");
#extraire les blocs d'un fichier ( blocs séparés par une ligne blanche(=vide ) )
BLOCS:
while (<FICHIER_DE_DOUBLONS>) {
chomp;
$toutes_lignes++;
print "$toutes_lignes Lignes explorées:\t"; #DEBUG
print "$_ "; #DEBUG
if ( /^$/ .. /^$/ ) { ## NOUVEAU BLOC
#Chaque ligne entre les lignes vides est traitée
#traiter chaque ligne du bloc
$blocs_retenus++;
$num_ligne_par_bloc = 0;
print "Fin du bloc n° $blocs_retenus \n"; #DEBUG
LIGNE:
#Doit elle être la référence ?
#si oui: Faire une copie sans accès écriture
# attention aux modif. involontaires avec les liens physiques !
#Transformer les doublons en liens−physiques
}
else {
## C'est ici que les lignes du bloc seront traitées !
#print "$_ \n"; # DEBUG
$num_ligne_retenue++;
$num_ligne_par_bloc++;
# print "Ligne retenue: N° $num_ligne_retenue\n" ; #DE
print "Ligne retenue: n° $num_ligne_par_bloc\n"; #DEBUG
} ## Fin de if
} ## Fin de while BLOC
close FICHIER_DE_DOUBLONS;
print
"\n −> $num_ligne_retenue lignes retenues et $blocs_retenus blocs dans
le fichier n° $numero_fichier; \n"; #DEBUG
#print "Fin du fichier de doublons n° $numero_fichier\n\n"; #DEBUG
} ## Fin de foreach $fichier_de_doublons
print "FINI\n"; #DEBUG
exit 1;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[1] Travaux pratiques autodidactiques, sans aucune garantie, qu’on se le dise !
[2] avec 3 fichiers de doublons de : 27k, 5m, 38m
webmaster
Articles de cet auteur
fr
GNU, LINUX, BSD, LL
AIDES GNU/LINUX
PERL
?

