Leser: 27
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
#! /usr/bin/perl use strict; # strict verwenden use warnings; # ebenso Warnungen einschalten use File::Spec; # Modul zum Zusammensetzen von Dateipfaden use File::Copy; # Modul zum Kopieren/Verschieben von Dateien use File::Path; # Modul zum rekursiven Erstellen von Verzeichnissen # Hilfe/Details zu den Modulen: ($modulename entsprechend ersetzen) # http://search.cpan.org/perldoc?$modulname # globaler Hash mit Pfadinformationen my %path = ( sectioninfo => '/tmp/section_info.x', dst_dir => '/tmp/sections', src_dir => '/tmp/source_sections', ); # sub routinen # ---------------------------------------------------------- sub read_blocks_from_file { my ( $filename, $separator ) = @_; open my $fh, '<', $filename or die "open(ro) failed: $filename: $!\n"; local $/ = $separator; chomp( my @blocks = <$fh> ); close $fh; return @blocks; } sub parse_block { my ( $block ) = @_; # trenne Block in Zeilen auf; erste Zeile: Sektion; restliche Zeilen: Dateien my ( $section, @files ) = split m{$/}, $block; return $section, @files; } sub copy_files_from_to { # aRef: Array-Referenz auf Array mit Dateinamen my ( $aRef, $srcdir, $dstdir ) = @_; for my $file ( @$aRef ) { my $srcfile = File::Spec->catfile( $srcdir, $file ); copy( $srcfile, $dstdir ) or die "copy $srcfile to $dstdir failed: $!\n"; } } # main skript # ---------------------------------------------------------- # lese blockweise ein; jeder Block wird von zwei Umbruechen abgeschlossen my @blocks = read_blocks_from_file( $path{sectioninfo}, $/x2 ); # jeden Block einzeln betrachten for my $block ( @blocks ) { my ( $section, @files ) = parse_block( $block ); my $destination = File::Spec->catdir( $path{dst_dir}, $section ); # lege Verzeichnis $destination an, wenn noch nicht vorhanden if ( ! -e $destination ) { mkpath $destination or die "mkdir $destination failed: $!\n"; } # sterbe mit Fehler, wenn $destination existiert und kein Verzeichnis ist elsif ( !-d $destination ) { die "$destination is not a directory: $!\n"; } copy_files_from_to( \@files, $path{src_dir}, $destination ); } __END__
1 2 3 4 5 6 7 8 9
#----------------------------------------------------------------------------------------------------------------------- # globaler Hash mit Pfadinformationen my %path = ( sectioninfo => '/tmp/section_info.x', dst_dir => '/tmp/sections', # ?-> Pfad, in das die Dateien kopiert werden sollen? src_dir => '/tmp/source_sections', # ?-> Pfad, in dem die zu kopierenden Dateien liegen? ); #-----------------------------------------------------------------------------------------------------------------------
1
2
3
4
5
6
# globaler Hash mit Pfadinformationen
my %path = (
sectioninfo => '/tmp/section_info.x', # kompletter Pfad zur Datei "Sektionsinfo.x"
dst_dir => '/tmp/sections', # Verzeichnispfad, wohin die Dateien kopiert werden
src_dir => '/tmp/source_sections', # Verzeichnispfad, von wo die Dateien kopiert werden
);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
#! /usr/bin/perl #------------------------------------------------------------------------ #Einlesen der Section_Data in das Perl-Skript zur "Weiterverarbeitung" #------------------------------------------------------------------------ @allSec = (""); #Def eines array, in das die Daten aller sections zeilenweise geschrieben werden #Öffnen der Datei, Schreiben der Daten in das array @allSec open(SECDATA, "</home/../sectionInfo.dat") || die "Datei nicht gefunden\n"; while(<SECDATA>) { push(@allSec,$_); #Feldelemente $_ in array "@allsec" schreiben } close(SECDATA); #------------------------------------------------------------------------ #Schreiben der Daten der n Sektionen in n arrayas @secData_$i #------------------------------------------------------------------------ while(my $zeile=<@allSec>) { $i=1; if($zeile=~ m/^datei1\.dat/ .. $zeile=~ m/^datei1\.dat/g) { push(@{$secData_[$i]},$_); $i++; } } #------------------------------------------------------------------------ #Ausgabe der Daten der n Sektionen #------------------------------------------------------------------------ for($j=1; $j<=$i; $j++) { print "Daten der Sektion $j \n"; print @{$secData_[$j]}; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
#!/usr/bin/perl use strict; # strict verwenden use warnings; # ebenso Warnungen einschalten use File::Spec; # Modul zum Zusammensetzen von Dateipfaden use File::Copy; # Modul zum Kopieren/Verschieben von Dateien use File::Path; # Modul zum rekursiven Erstellen von Verzeichnissen # Hilfe/Details zu den Modulen: ($modulename entsprechend ersetzen) # http://search.cpan.org/perldoc?$modulname my $file='sector_file.txt'; # globaler Hash mit Pfadinformationen my %path = ( sectioninfo => '/tmp/section_info.x', # kompletter Pfad zur Datei "Sektionsinfo.x" dst_dir => '/tmp/sections', # Verzeichnispfad, wohin die Dateien kopiert werden src_dir => '/tmp/source_sections', # Verzeichnispfad, von wo die Dateien kopiert werden section => 'Sek_1', # Angabe der Sektion die kopiert werden soll, # wenn er Eintrag leer undef oder nicht vorhanden ist, # so werden alle gefundenen Sektionen Kopiert ); # lese Die Sektioninfos ein my $sections = parse_file( $path{sectioninfo}, $path{section} ); # jede Sektion einzeln betrachten for my $section_name ( keys{%$sections} ) { # Prüfen ob die Sektion kopiert werden soll next if($path{section} && $section_name ne $path{section}); # Zielpfad ermitteln my $destination = File::Spec->catdir( $path{dst_dir}, $section_name ); # lege Verzeichnis $destination an, wenn noch nicht vorhanden if ( ! -e $destination ) { mkpath $destination or die "mkdir $destination failed: $!\n"; } # sterbe mit Fehler, wenn $destination existiert und kein Verzeichnis ist elsif ( !-d $destination ) { die "$destination is not a directory: $!\n"; } # Dateien Kopieren copy_files_from_to( $sections->{$section_name}, $path{src_dir}, $destination ); } ######################################################################## sub parse_file { my $file=shift; # wenn kein Sektorname angeben gib alle Sektoren zurück. my $sector=shift; # wenn $sector nur eine Zahl ist, den Vollständigen Namen ergänzen $sector="Sek_$sector" if(defined($sector) && $sector=~/^\d+$/); open(my $fh, '<', $file) or die("Error open $file ($!)\n"); my $ret={}; my $sector_now; my $last_line=''; while(my $line=<$fh>) { chomp($line); # Sektordefinitionen beginnen immer mit einem "Sek_" gefolgt von einer Zahl if($line=~/(Sek_\d+)/) { # Ausnahmeregelung wenn nur ein Sektor gesucht ist if($sector) { if($1 eq $sector) { $sector_now=$1 } # abbrechen wenn der Sektor vollständig gelesen wurde elsif($sector_now && $sector_now eq $sector) { last } } else { $sector_now=$1; } # $line leeren, # sonst wird später die erste Datei nicht gefunden. $line=''; } # ein Sektor wurde gefunden # nun hole alle Dateinamen. # Sie stehen immer hinter einer leeren Zeile elsif($sector_now && $line!~/^\s*$/ && $last_line=~/^\s*$/) { my $fname=$line; chomp($fname); push(@{$ret->{$sector_now}},$fname); } # letzte zeile speichern, # um später zu testen, ob sie leer ist $last_line=$line; } close($fh); return $ret; } _END_
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
#!/usr/bin/perl use strict; # strict verwenden use warnings; # ebenso Warnungen einschalten # lese Die Sektioninfos ein my $sections = parse_file( 'section_info.x' ); for my $section_name (sort keys(%$sections)) { print "$section_name\n"; for my $file_name (sort keys(%{$sections->{$section_name}})) { print " $file_name\n"; my $data=$sections->{$section_name}->{$file_name}; $data=~s/(^|\n)/$1 /g; print "$data\n"; } print "#"x70,"\n\n" } ######################################################################## sub parse_file { my $file=shift; # wenn kein Sektorname angeben gib alle Sektoren zurück. my $sector=shift; # wenn $sector nur eine Zahl ist, den Vollständigen Namen ergänzen $sector="Sek_$sector" if(defined($sector) && $sector=~/^\d+$/); open(my $fh, '<', $file) or die("Error open $file ($!)\n"); my $ret={}; my $sector_now; my $fname=undef; my $last_line=''; while(my $line=<$fh>) { chomp($line); # Sektordefinitionen beginnen immer mit einem "Sek_" gefolgt von einer Zahl if($line=~/(Sek_\d+)/) { # Ausnahmeregelung wenn nur ein Sektor gesucht ist if($sector) { if($1 eq $sector) { $sector_now=$1 } # abbrechen wenn der Sektor vollständig gelesen wurde elsif($sector_now && $sector_now eq $sector) { last } } else { $sector_now=$1; } # $line leeren, # sonst wird später die erste Datei nicht gefunden. $line=''; $fname=undef; } # ein Sektor wurde gefunden # nun hole alle Dateinamen. # Sie stehen immer hinter einer leeren Zeile oder einer Zeile mit '....' elsif($sector_now && $line!~/^(?:\s*|\.{3,})$/ && $last_line=~/^(?:\s*|\.{3,})$/) { $fname=$line; $ret->{$sector_now}->{$fname}=''; } # alles bis zur nächsten leeren Zeile oder '....' Zeile ist der Dateinhalt elsif($sector_now && $fname && $line!~/^(?:\s*|\.{3,})$/) { $ret->{$sector_now}->{$fname}.="$line\n"; } # letzte Zeile speichern, # um später zu testen, ob sie leer ist, oder '....' enthält $last_line=$line; } close($fh); return $ret; }
2010-10-01T07:34:17 Sannytopeg:"Ein Sektor besteht aus einer Reihe von Blöcken dessen 'Titel' den Dateinamen repräsentieren. der Inhalt folgt bis zu einer leeren Zeile oder einer reihe von '.....' Beliebiger Anzahl."
-> AW:Ein Sektor besteht aus einer Reihe von Blöcken dessen 'Titel' den Dateinamen repräsentieren. der Inhalt folgt bis zu einer leeren Zeile.
1
2
3
4
5
6
7
8
9
10
11
Sektion 1
datei.a
datei.b
datei.c
datei.d
Sektion 2
datei.a
datei.b
datei.c
datei.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Sek_Data
Number of Sections: n
Sek_1
datei1.dat
Etwas Text
.........
datei2.dat
Etwas Text
.........
datei3.dat
Etwas Text
datei4.tmp
............
datei5.tmp
.............
Sek_2
datei1.dat
.......
datei2.dat
.......
datei3.dat
......
datei4.tmp
............
datei5.tmp
.............
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Sek_1
datei1.dat
Etwas Text
datei2.dat
Etwas Text
datei3.dat
Etwas Text
datei4.tmp
Etwas Text
datei5.tmp
Etwas Text
Sek_2
datei1.dat
Etwas Text
datei2.dat
Etwas Text
datei3.dat
Etwas Text
datei4.tmp
Etwas Text
2010-10-01T07:34:17 Sannytopeg:"Wer zum .... hat sich ein solches Dateiformat ausgedacht?! Keine eindeutigen Trenner! Wer macht so was?? Wie soll man zuverlässig das Ende der Datei erkennen?"
AW: Was für ein Dateiformat/ Strukturierung kannst du empfehlen, wenn man die Daten unterschiedlicher Dateien in eine zusammenfassen will, um mit diesen möglichst gut (weiter-)arbeiten zu können?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
SECFILE V2
trenner----------------------------------------------------------trenner
COMMENT
Wie man sehen kann beginnt die Datei mit einem "magischen" Wort.
Damit erkennt der Parser das er die datei parsen kann.
Die Zweite Zeile ist der Trenner, der Blöcke, die in der Datei verwendet werden soll.
Er sollte eindeutig sein, damit er nicht zufällig als Dateiinhalt auftaucht.
Es sind bisher drei Blocktypen definiert, die durch den Trenner getrennt werden:
SECTION: Definiert den beginn einer Sektion gefolgt vom Namen
FILE: Definiert eine datei gefolgt vom Dateinamen und den Inhalt
COMMENT: Kommentare, werden beim Parsen ignoriert.
Weitere Typen können definiert werden,
Unbekannte Typen werden (mit einer Warnung) ignoriert,
sodaß auch spätere Formatgeneratonen wenigstens teilweile
mit einem älteren Parser gelesen werden können
trenner----------------------------------------------------------trenner
SECTION
Sektion 1
trenner----------------------------------------------------------trenner
FILE
test1.txt
bla bla bla
trenner----------------------------------------------------------trenner
FILE
test2.txt
bla bla bla
trenner----------------------------------------------------------trenner
FILE
test3.txt
bla bla bla
trenner----------------------------------------------------------trenner
SECTION
Sektion 2
trenner----------------------------------------------------------trenner
FILE
test1.txt
bla bla bla
trenner----------------------------------------------------------trenner
FILE
test2.txt
bla bla bla
trenner----------------------------------------------------------trenner
FILE
test3.txt
bla bla bla
trenner----------------------------------------------------------trenner
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; print Dumper(parse('file.sec')); sub parse { my $file=shift; return undef unless($file); my $sec=shift; my $fname=shift; my %ret; open(my $fh, '<', $file) or die("error open $file $!\n"); if(<$fh> ne "SECFILE V2\n") { warn("Ungültiges Dateiformat!\n"); return undef; } my $trenner=<$fh>; local $/="\n$trenner"; my $section=$sec?undef:'DEFAULT'; while(my $block=<$fh>) { chomp($block); $block=~s/^\s+//s; my ($type,$name,$data)=split(/\n/,$block,3); next unless(defined($type)); $name=~s/^\s+//; if($type eq 'SECTION') { if(defined($sec)) { if($name eq $sec) { $section=$name } else { $section=undef; } } else { $section=$name; } } elsif($type eq 'FILE') { next unless(defined($section)); $data='' unless(defined($data)); if(defined($fname)) { $ret{$section}{$name}=$data if($fname eq $name); } else { $ret{$section}{$name}=$data }; } elsif($type eq 'COMMENT'){} # mache nichts... else { warn("Unbekannter Blocktyp: $type, Wird ignoriert!\n");} } close $fh; return \%ret; }