Thread Datei lesen und in Hash schreiben? (45 answers)
Opened by Math55 at 2004-01-18 22:12

Dubu
 2004-01-20 18:28
#79285 #79285
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
Na gut... ;)

Hier ist eine Version, die mit der bisherigen Spezifikation zurecht kommt. Um die Datenstruktur etwas klarer zu machen, habe ich gleich noch eine Ausgabe dazu programmiert. Bis auf Whitespace wird damit die Originaldatei rekonstruiert, inkl. Reihenfolge der Schluessel und Werte.

Code: (dl )
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
#!/usr/bin/perl
use strict;
use warnings;

my %params;

open PARAM, "param.dat" or die $!;

my $currentkeyword = '';
my $currentvalue = '';
my @freecomments = ();
my $continued = 0;
while (<PARAM>) {
   chomp;
   # Leerzeichen vorne/hinten loeschen
   s/^\s+//;
   s/\s+$//;

   # Diese Zeile fortsetzen?
   if (/\\$/) {
       chop;
       # evtl. nochmal Leerzeichen am Ende loeschen
       s/\s+$//;
       $continued = 1;
   } else {
       $continued = 0;
   }

   if (/^#\s*(.*)/) {  # nur Kommentar
       if (length $currentkeyword && length $currentvalue) {   # Kommentar zu einem Wert
           push @{$params{$currentkeyword}{comments}{$currentvalue}}, $1;
       } else {                # freier Kommentar
           push @freecomments, $1;
       }
   } elsif (length) {          # keine Leerzeile
       my ($ktemp, $ctemp);    # Hilfsvariablen

       if (/^(.+?)\s*#\s*(.*)/) {      # Zeile mit Kommentar?
           ($ktemp, $ctemp) = ($1, $2);
       } else {
           ($ktemp, $ctemp) = ($_, '');
       }

       if (length $currentkeyword) {   # Wenn es ein aktuelles Keyword gibt ...
           $currentvalue = $ktemp;     # ... Wert merken ...
       } elsif (index ($ktemp, '=') >=0) { # ansonsten muss es "Schluessel = Wert" sein
           ($currentkeyword, $currentvalue) = split /\s*=\s*/, $ktemp, 2;
           push @{$params{keywords}}, $currentkeyword;
       } else {                        # keine korrekte Syntax
           die "Syntaxfehler in Zeile $.";
       }
       # Jetzt neuen Wert im Array @{$params{$currentkeyword}{values}} merken ...
       push @{$params{$currentkeyword}{values}}, $currentvalue;
       # ... und evtl. Kommentar dazu im Array @{$params{$currentkeyword}{comments}{$currentvalue}} ablegen.
       push @{$params{$currentkeyword}{comments}{$currentvalue}}, $ctemp if length $ctemp;
   }

   # Wenn die naechste Zeile Fortsetzung ist, bei neuer Zeile weiter ...
   next if $continued;

   # ... ansonsten freie Kommentare beim Keyword speichern und Keyword loeschen
   if (length $currentkeyword && @freecomments) {
       @{$params{$currentkeyword}{precomments}} = ( @freecomments );
       @freecomments = ();
   }
   ($currentkeyword, $currentvalue) = ('', '');

}

#### Testausgabe!
# use Data::Dumper;
# print Dumper \%params;
# exit;

#############################################

# Jetzt wieder ausgeben!

# Fuer alle Keywords
for my $key (@{$params{keywords}}) {
   # erst die freien Kommentare, falls vorhanden
   if (exists $params{$key}{precomments}) {
       print "# ", $_, "\n" for @{$params{$key}{precomments}};
   }

   # dann die einzelnen Schluessel und Werte
   print "$key = ";
   my @vals = ();
   foreach my $val (@{$params{$key}{values}}) {
       my $str = $val;
       if (exists $params{$key}{comments}{$val}) {
           $str .= "\t# " . join " \\\n\t\t\t# ", @{$params{$key}{comments}{$val}};
       }
       push @vals, $str;
   }
   print join " \\\n\t\t", @vals;
   print "\n";
}


Edit: Die Datenstruktur sieht uebrigens wie folgt aus.

Der Hash %params hat
- einen Eintrag keywords, in dem alle Schluesselworte in der Reihenfolge ihres Vorkommens stehen und
- fuer jedes Schluesselwort einen weiteren Eintrag.

Jeder Schluesselworteintrag verweist auf einen Hash mit folgenden Eintraegen:
* 'precomments' - zeigt auf eine Array mit Kommentaren, die vor der Zeile mit diesem Schluessel standen,
* 'values' - zeigt auf ein Array mit den Werten fuer diesen Schluessel, in der Reihenfolge ihres Auftretens
* 'comments' - zeigt wiederum auf einen Hash, der fuer jeden kommentierten Wert die Kommentare enthaelt.

'precomments' und 'comments' sind dabei fakultativ, d.h. nur nach Bedarf gefuellt. 'values' enthaelt mindestens einen Wert, der aber leer sein kann.\n\n

<!--EDIT|Dubu|1074616626-->

View full thread Datei lesen und in Hash schreiben?