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.
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-->