5 # Dieses Perl-Skript generiert aus einer gegebenen Liste von Wörtern, die
6 # mit Trennstellenmarkern für die reformierte Rechtschreibung versehen sind,
7 # Einträge für traditionelle deutsche und schweizerdeutsche Rechtschreibung
8 # sowie Versalformen (traditionell und reformiert) im Format der
9 # »wortliste«-Datei. Es akzeptiert zusätzlich eine Liste von Ausnahmen, die
10 # bereits im Format der »wortliste«-Datei sein müssen und durch das Skript
11 # erzeugte Einträge überschreiben, wobei das erste Feld als Schlüssel
14 # Wenn man versucht, »wortliste« aus den eigenen reformierten Wortformen zu
15 # erzeugen und Ausnahmen unberücksichtigt läßt, stimmen die Resultate zu
16 # mehr als 99.95% überein.
18 # Aufruf (zur Lesbarkeit auf mehrere Zeilen aufgeteilt):
20 # perl [--debug] erzeuge-wortliste.pl \
21 # [liste1 liste2 ...] \
22 # [+ ausnahme1 ausnahme2 ...] > ausgabe
24 # Das Zeichen »+« trennt die Wortlistedateien von den Ausnahmedateien.
26 # Die Eingabedateien müssen in UTF-8 kodiert sein; als Zeilenformat wird
27 # entweder eine ein- oder zweispaltige Liste (mit »;« als Feldtrenner)
28 # akzeptiert, wobei Kommentare mit »#« beginnen und unmodifiziert ausgegeben
31 # Beispiel;Bei<spiel # Format 1
32 # Bei<spiel # Format 2
34 # Dateiname »-« entspricht der Standardeingabe. Sind keine Eingabedateien
35 # angegeben, verwendet das Skript ebenfalls die Standardeingabe. Beispiel:
37 # perl erzeuge-wortliste.pl < reformiert > wortliste.erzeugt
39 # Die Ausgabe erfolgt unsortiert und sollte mit dem Skript »sort.py«
40 # weiterverarbeitet werden.
42 # Im folgenden Beispiel befinden sich die reformierten Einträge in den
43 # Dateien »a.reformiert«, »b.reformiert« usw.; die Ausnahmen sind in den
44 # Dateien »a.ausnahmen«, »b.ausnahmen« usw. Eine sortierte Wortliste kann
47 # perl erzeuge-wortliste.pl *.reformiert + *.ausnahmen \
48 # | python sort.py -d \
49 # > wortliste.komplett
53 # Option »--debug« gibt zusätzlich die vom Skript bestimmten Wortformen aus.
57 use utf8
; # String-Literals direkt als UTF-8.
58 use open qw(:std :utf8);
59 use feature
'unicode_strings';
60 use Getopt
::Long
qw(:config no_ignore_case
63 use List
::MoreUtils
'first_index';
67 GetOptions
("debug" => \
$debug);
70 # Analyse der Wortbestandteile
71 # ----------------------------
73 # Wir verwenden Subroutinen, um die folgenden Trennvarianten abzudecken:
75 # reformierte Rechschreibung,
76 # traditionelle Rechtschreibung,
78 # reformierte Rechtschreibung, Versalform,
79 # traditionelle Rechtschreibung, Versalform,
81 # traditionelle schweizerdeutsche Rechtschreibung.
83 # Beachte: Die Wortliste hat keine separaten Einträge für traditionelle
84 # schweizerdeutsche Versalformen; diese fallen entweder mit den
85 # traditionellen Versalformen oder den traditionellen schweizerdeutschen
88 # Beachte weiters, daß sich Einträge für reformierte und traditionelle
89 # Rechtschreibung teilweise widersprechen und daher separat behandelt werden
90 # müssen; die Einträge für traditionelle deutsche und schweizerdeutsche
91 # Rechtschreibung dagegen nicht. Aus diesem Grund ist die Wortliste für
92 # traditionelle schweizerdeutsche Rechtschreibung einfach eine Obermenge der
93 # Wortliste für die traditionelle deutsche Rechtschreibung; etwaige
94 # »Fehleinträge« der traditionellen schweizerdeutschen Rechtschreibung (z.B.
95 # »süsssauer« statt dem korrekten »süssauer«) werden nicht entfernt.
98 # Die Subroutinen modifizieren direkt das an sie übergebene Argument; die
99 # Subroutinen-Varianten mit angehängtem »_« sind für Wörter ohne
100 # Trennstellenmarker.
103 # »s-t« -> »-st« (ref. -> trad.)
104 # (ref. -> trad. versal)
105 # (ref. -> trad. schweiz.)
108 # Kno-ten=äs-te -> Kno-ten=äste
110 $_[0] =~ s
/(?
: (?
<= \W \w
)
115 # Tes[-ter=/t=er<.]ken-nung -> Te[-ster=/st=er<.]ken-nung
116 $_[0] =~ s
/(?
<= \w
[^s
] )
127 # (fass-te -> fass-te)
128 $_[0] =~ s
/(?
<= \w
[^s
] )
138 # »-ck« -> »{ck/k-k}« (ref. -> trad.)
139 # (ref. -> trad. versal)
140 # (ref. -> trad. schweiz.)
143 # Dru[-cker=/ck=er<.]zeug>nis -> Dru[{ck/k-k}er=/ck=er<.]zeug>nis
151 /[{ck\/k
-k
}$1\
/ck$2]/xg;
153 # He-cke -> He{ck/k-k}e
154 $_[0] =~ s
/[^\w\/\
[\
]\
{\
}]+
158 # Stau[=be-/b=e]cken -> Stau[=b/b=]e{ck/k-k}en
159 $_[0] =~ s
/\
[ (.*?
) (.)
166 /[$1\/$3]${2}{ck\
/k-k}/xg;
169 # Buch=ecker -> Buch=e{ck/k-k}er
171 # (Vier=eck -> Vier=eck)
173 $_[0] =~ s
/(?: (?<= [^\w\/\
[\
]\
{\
}] \w
)
185 # »-ß« -> »s-s« (ref. -> ref. versal)
186 # (ref. -> trad. schweiz.)
188 sub bindestrich_ß_1
{
195 # auf<aßen -> auf<as-sen
197 # (auf<aßt -> auf<aßt)
198 $_[0] =~ s
/(?
: (?
<= \W \w
)
205 sub bindestrich_ß_1_
{
210 $_[0] =~ s
/(?
: (?
<= \W \w
)
218 # »-ß« -> »-ss« (ref. -> trad. versal)
220 sub bindestrich_ß_2
{
226 sub bindestrich_ß_2_
{
232 # »ß-s« -> »{ss/ss-s}« (ref. -> trad. schweiz)
235 # süß=sau-er -> sü{ss/s=s}au-er
236 # (Süß=stoff -> Süß=stoff)
253 # »ß« -> »ss« (ref. -> ref. versal)
254 # (ref. -> trad. versal)
255 # (ref. -> trad. schweiz.)
257 # Diese Regel ist nach den spezielleren ß-Regeln weiter oben anzuwenden.
272 # »ss-s« -> »{ss/ss-s}« (ref. -> trad. schweiz.)
275 # Ess=sucht -> E{ss/ss=s}sucht
276 # (Biss=spur -> Biss=spur)
293 # »ss« -> »ß« (ref. -> trad.)
296 # biss=fest -> biß=fest
299 # (Fa-desse -> Fa-desse)
301 (?
= (?
: [b
-df
-hj
-np
-rtv
-z
]
309 (?
= (?
: [b
-df
-hj
-np
-rtv
-z
]
316 # »xx-x« -> »{xx/xx-x}« (ref. -> trad.)
317 # (ref. -> trad. versal)
318 # (ref. -> trad. schweiz.)
320 # Buchstabe »x« ist irgendein Konsonant außer »s«.
323 # Bau=stoff==fir-ma -> Bau=sto{ff/ff==f}ir-ma
324 # (Griff=flä-che -> Griff=flä-che)
325 $_[0] =~ s
/([b
-df
-hj
-np
-rtv
-z
]) \g
{1} (\W
+) \g
{1}
327 /{$1$1\/$1$1$2$1}/xg
;
329 # Kipp=phä-no-men -> Ki{pp/pp=p}hä-no-men
330 $_[0] =~ s
/([prt
]) \g
{1} (\W
+) \g
{1}
332 /{$1$1\/$1$1$2$1}/xg
;
336 $_[0] =~ s
/([b
-df
-hj
-np
-rtv
-z
]) \g
{1} \W
+ \g
{1}
340 $_[0] =~ s
/([prt
]) \g
{1} \W
+ \g
{1}
346 sub entferne_marker
{
349 # [»Variante A«/»Variante B«] -> »Variante A«
353 # Dru[-cker=/ck=er<.]zeug>nis -> Dru-cker=zeug>nis
355 # Beachte, daß {.../...} bei reformierter Rechtschreibung nicht auftreten
357 $_[0] =~ s/\[ (.*?) \/ .*? \]/$1/gx
;
363 # Gebe eine Zeile aus, unter Berücksichtigung der möglichen Zeilenformate.
367 $ref_wort, $ref_trennung,
368 $ref_versal_wort, $ref_versal_trennung,
369 $trad_wort, $trad_trennung,
370 $trad_versal_wort, $trad_versal_trennung,
371 $trad_schweiz_wort, $trad_schweiz_trennung,
374 # Eliminiere Wortformen, die nicht mit »wort« übereinstimmen.
375 $ref_trennung = "" if $wort ne $ref_wort;
376 $ref_versal_trennung = "" if $wort ne $ref_versal_wort;
377 $trad_trennung = "" if $wort ne $trad_wort;
378 $trad_versal_trennung = "" if $wort ne $trad_versal_wort;
379 $trad_schweiz_trennung = "" if $wort ne $trad_schweiz_wort;
382 if ($ref_trennung eq $trad_trennung
383 && length($ref_trennung)) {
385 . $ref_trennung; # Feld 2
391 . (length($trad_trennung) ?
$trad_trennung
394 . (length($ref_trennung) ?
$ref_trennung
397 if ($ref_trennung ne $ref_versal_trennung
398 || $trad_trennung ne $trad_versal_trennung
399 || $trad_trennung ne $trad_schweiz_trennung) {
400 if ($ref_versal_trennung eq $trad_versal_trennung
401 && ($ref_versal_trennung eq $trad_schweiz_trennung
402 || !$trad_schweiz_trennung)) {
403 if (length($ref_versal_trennung)) {
405 . $ref_versal_trennung; # Feld 5
412 . (length($trad_versal_trennung) ?
$trad_versal_trennung
415 . (length($ref_versal_trennung) ?
$ref_versal_trennung
419 if ($trad_versal_trennung eq $trad_schweiz_trennung) {
423 print length($trad_schweiz_trennung) ?
$trad_schweiz_trennung
430 # Kommentare werden nur einmal für Einträge in der reformierten
431 # Schreibweise ausgegeben.
432 print " " . $kommentar if $kommentar && $wort eq $ref_wort;
441 # Wir geben zuerst die Wörter in den Ausnahmedateien in ein Hash.
444 # Alle Argumente nach dem »+«-Zeichen sind Ausnahmedateien.
445 my $index = first_index
{ $_ eq "+" } @ARGV;
447 my @listendateien = splice(@ARGV, 0, $index + 1);
450 # Leere Zeilen und Kommentarzeilen werden ignoriert.
451 next if /^ \s* (?: $ | \# )/x;
453 # Zerlege Zeile in erstes Feld und Rest.
454 my @zeile = split(";", $_, 2);
455 $ausnahmen{$zeile[0]} = $zeile[1];
458 # Konstruiere die Argumentliste für die nächste »while«-Schleife.
459 @ARGV = @listendateien;
464 # Gebe Kommentarzeilen direkt aus.
472 # Zerlege Zeile in ihre Bestandteile. Mögliche Formate:
474 # foobar;foo-bar # blabla
485 my $kommentar = defined $2 ?
$2 : "";
488 # Wir konstruieren jetzt alle möglichen Wortformen - der Benutzer muß
489 # natürlich trotzdem alles kontrollieren.
491 # Die Ausgabe erfolgt unsortiert.
493 # reformierte Rechtschreibung
494 my $ref_trennung = $trennung;
496 my $ref_wort = $trennung;
497 entferne_marker
($ref_wort);
499 # reformierte Rechtschreibung, Versalform
500 my $ref_versal_trennung = $trennung;
501 bindestrich_ß_1
($ref_versal_trennung);
502 ß
($ref_versal_trennung);
504 my $ref_versal_wort = $trennung;
505 bindestrich_ß_1_
($ref_versal_wort);
506 ß_
($ref_versal_wort);
507 entferne_marker
($ref_versal_wort);
509 # traditionelle Rechtschreibung
510 my $trad_trennung = $trennung;
514 xx_x
($trad_trennung);
516 my $trad_wort = $trennung;
521 entferne_marker
($trad_wort);
523 # traditionelle Rechtschreibung, Versalform
524 my $trad_versal_trennung = $trennung;
525 s_t
($trad_versal_trennung);
526 ck
($trad_versal_trennung);
527 bindestrich_ß_2
($trad_versal_trennung);
528 ß
($trad_versal_trennung);
529 xx_x
($trad_versal_trennung);
531 my $trad_versal_wort = $trennung;
532 s_t_
($trad_versal_wort);
533 ck_
($trad_versal_wort);
534 bindestrich_ß_2_
($trad_versal_wort);
535 ß_
($trad_versal_wort);
536 xx_x_
($trad_versal_wort);
537 entferne_marker
($trad_versal_wort);
539 # traditionelle Rechtschreibung, schweizerdeutch
540 my $trad_schweiz_trennung = $trennung;
541 s_t
($trad_schweiz_trennung);
542 ck
($trad_schweiz_trennung);
543 bindestrich_ß_1
($trad_schweiz_trennung);
544 ß_s
($trad_schweiz_trennung);
545 ß
($trad_schweiz_trennung);
546 ss_s
($trad_schweiz_trennung);
547 xx_x
($trad_schweiz_trennung);
549 my $trad_schweiz_wort = $trennung;
550 s_t_
($trad_schweiz_wort);
551 ck_
($trad_schweiz_wort);
552 bindestrich_ß_1_
($trad_schweiz_wort);
553 ß_s_
($trad_schweiz_wort);
554 ß_
($trad_schweiz_wort);
555 ss_s_
($trad_schweiz_wort);
556 xx_x_
($trad_schweiz_wort);
557 entferne_marker
($trad_schweiz_wort);
565 print "ref. versal: "
568 . $ref_versal_trennung
575 print "trad. versal: "
578 . $trad_versal_trennung
580 print "trad. schweiz: "
583 . $trad_schweiz_trennung
592 # Wir bilden einen Hash, um Doubletten der möglichen Wortformen und
593 # Wortformen kürzer als vier Buchstaben zu entfernen.
594 my %wortformen = map { length($_) > 3 ?
($_, 1)
602 foreach my $wort (keys %wortformen) {
603 if (defined($ausnahmen{$wort})) {
604 print $wort . ";" . $ausnahmen{$wort};
606 # Entferne Ausnahmeeintrag vom »ausnahmen«-Hash.
607 delete $ausnahmen{$wort};
611 $ref_wort, $ref_trennung,
612 $ref_versal_wort, $ref_versal_trennung,
613 $trad_wort, $trad_trennung,
614 $trad_versal_wort, $trad_versal_trennung,
615 $trad_schweiz_wort, $trad_schweiz_trennung,
622 # Abschließend geben wir die restlichen Ausnahmen aus.
623 foreach my $wort (keys %ausnahmen) {
624 print $wort . ";" . $ausnahmen{$wort};