Python Skript update.
[wortliste.git] / skripte / erzeuge-wortliste.pl
blobf511113ed19c57b48892f9393e973cf4a8f96750
1 #! /usr/bin/perl -w
3 # erzeuge-wortliste.pl
5 # Dieses Perl-Skript generiert, aus einer gegebenen Liste von Wörtern
6 # versehen mit Trennstellenmarkern für die reformierte Rechtschreibung,
7 # Einträge für traditionelle deutsche und schweizerdeutsche Rechtschreibung
8 # sowie Versalformen (sowohl traditionell und reformiert) im Format der
9 # »wortliste«-Datei.
11 # Wenn man versucht, »wortliste« aus den eigenen reformierten Wortformen zu
12 # erzeugen, stimmen die Resultate zu mehr als 99.95% überein.
14 # Aufruf
16 # perl [--debug] erzeuge-wortliste.pl [liste1 liste2 ...] > ausgabe
18 # Die Eingabedateien müssen in UTF-8 kodiert sein; als Zeilenformat wird
19 # entweder eine ein- oder zweispaltige Liste (mit »;« als Feldtrenner)
20 # akzeptiert, wobei Kommentare mit »#« beginnen und unmodifiziert ausgegeben
21 # werden. Beispiele:
23 # Beispiel;Bei<spiel # Format 1
24 # Bei<spiel # Format 2
26 # Sind keine Eingabedateien angegeben, verwendet das Skript die
27 # Standardeingabe. Beispiel:
29 # perl erzeuge-wortliste.pl reformiert > wortliste.erzeugt
31 # Die Ausgabe erfolgt unsortiert und sollte mit dem Skript »sort.py«
32 # weiterverarbeitet werden. Beispiel:
34 # perl erzeuge-wortliste.pl \
35 # < reformierte-wortliste \
36 # | python sort.py -d \
37 # > wortliste.komplett
39 # Option »--debug« gibt zusätzlich die vom Skript bestimmten Wortformen aus.
41 use strict;
42 use warnings;
43 use utf8; # String-Literals direkt als UTF-8.
44 use open qw(:std :utf8);
45 use feature 'unicode_strings';
46 use Getopt::Long qw(:config no_ignore_case no_auto_abbrev);
49 my $debug = "";
50 GetOptions("debug" => \$debug);
53 # Analyse der Wortbestandteile
54 # ----------------------------
56 # Wir verwenden Subroutinen, um die folgenden Trennvarianten abzudecken:
58 # reformierte Rechschreibung,
59 # traditionelle Rechtschreibung,
61 # reformierte Rechtschreibung, Versalform,
62 # traditionelle Rechtschreibung, Versalform,
64 # traditionelle schweizerdeutsche Rechtschreibung.
66 # Beachte: Die Wortliste hat keine separaten Einträge für traditionelle
67 # schweizerdeutsche Versalformen; diese fallen entweder mit den
68 # traditionellen Versalformen oder den traditionellen schweizerdeutschen
69 # Formen zusammen.
71 # Beachte weiters, daß sich Einträge für reformierte und traditionelle
72 # Rechtschreibung teilweise widersprechen und daher separat behandelt werden
73 # müssen; die Einträge für traditionelle deutsche und schweizerdeutsche
74 # Rechtschreibung dagegen nicht. Aus diesem Grund ist die Wortliste für
75 # traditionelle schweizerdeutsche Rechtschreibung einfach eine Obermenge der
76 # Wortliste für die traditionelle deutsche Rechtschreibung; etwaige
77 # »Fehleinträge« der traditionellen schweizerdeutschen Rechtschreibung (z.B.
78 # »süsssauer« statt dem korrekten »süssauer«) werden nicht entfernt.
81 # Die Subroutinen modifizieren direkt das an sie übergebene Argument; die
82 # Subroutinen-Varianten mit angehängtem »_« sind für Wörter ohne
83 # Trennstellenmarker.
86 # »s-t« -> »-st« (ref. -> trad.)
87 # (ref. -> trad. versal)
88 # (ref. -> trad. schweiz.)
90 sub s_t {
91 # Kno-ten=äs-te -> Kno-ten=äste
92 # Äs-te -> Äste
93 $_[0] =~ s/(?: (?<= \W \w )
94 | (?<= ^ \w ) )
95 s-t
96 /st/xg;
98 # Tes[-ter=/t=er<.]ken-nung -> Te[-ster=/st=er<.]ken-nung
99 $_[0] =~ s/(?<= \w [^s] )
100 s \[ \W+
102 (.*?)
105 (.*?)
107 /[-st$1\/st$2]/xg;
109 # fas-te -> fa-ste
110 # (fass-te -> fass-te)
111 $_[0] =~ s/(?<= \w [^s] )
113 /-st/xg;
116 sub s_t_ {
117 # Nichts zu tun.
121 # »-ck« -> »{ck/k-k}« (ref. -> trad.)
122 # (ref. -> trad. versal)
123 # (ref. -> trad. schweiz.)
125 sub ck {
126 # Dru[-cker=/ck=er<.]zeug>nis -> Dru[{ck/k-k}er=/ck=er<.]zeug>nis
127 $_[0] =~ s/\[ \W+
129 (.*?)
132 (.*?)
134 /[{ck\/k-k}$1\/ck$2]/xg;
136 # He-cke -> He{ck/k-k}e
137 $_[0] =~ s/[^\w\/\[\]\{\}]+
139 /{ck\/k-k}/xg;
141 # Stau[=be-/b=e]cken -> Stau[=b/b=]e{ck/k-k}en
142 $_[0] =~ s/\[ (.*?) (.)
145 (.*?) \g{2}
148 (?= [aeiouäöüy] )
149 /[$1\/$3]${2}{ck\/k-k}/xg;
151 # Ecke -> E{ck/k-k}e
152 # Buch=ecker -> Buch=e{ck/k-k}er
153 # (Eck -> Eck)
154 # (Vier=eck -> Vier=eck)
155 # (blockt -> blockt)
156 $_[0] =~ s/(?: (?<= [^\w\/\[\]\{\}] \w )
157 | (?<= ^ \w ) )
159 (?= [aeiouäöüy] )
160 /{ck\/k-k}/xg;
163 sub ck_ {
164 # Nichts zu tun.
168 # »-ß« -> »s-s« (ref. -> ref. versal)
169 # (ref. -> trad. schweiz.)
171 sub bindestrich_ß_1 {
172 # hei-ße -> heis-se
173 $_[0] =~ s/\W+
175 /s-s/xg;
177 # äße -> äs-se
178 # auf<aßen -> auf<as-sen
179 # (auf<aß -> auf<aß)
180 # (auf<aßt -> auf<aßt)
181 $_[0] =~ s/(?: (?<= \W \w )
182 | (?<= ^ \w ) )
184 (?= [aeiouäöüy] )
185 /s-s/xg;
188 sub bindestrich_ß_1_ {
189 $_[0] =~ s/\W+
191 /ss/xg;
193 $_[0] =~ s/(?: (?<= \W \w )
194 | (?<= ^ \w ) )
196 (?= [aeiouäöüy] )
197 /ss/xg;
201 # »-ß« -> »-ss« (ref. -> trad. versal)
203 sub bindestrich_ß_2 {
204 # hei-ße -> hei-sse
205 $_[0] =~ s/-ß
206 /-ss/xg;
209 sub bindestrich_ß_2_ {
210 $_[0] =~ s/-ß
211 /ss/xg;
215 # »ß-s« -> »{ss/ss-s}« (ref. -> trad. schweiz)
217 sub ß_s {
218 # süß=sau-er -> sü{ss/s=s}au-er
219 # (Süß=stoff -> Süß=stoff)
220 $_[0] =~ s/ß
221 (\W+)
223 (?= [aeiouäöüy] )
224 /{ss\/ss$1s}/xg;
227 sub ß_s_ {
228 $_[0] =~ s/ß
229 (\W+)
231 (?= [aeiouäöüy] )
232 /ss/xg;
236 # »ß« -> »ss« (ref. -> ref. versal)
237 # (ref. -> trad. versal)
238 # (ref. -> trad. schweiz.)
240 # Diese Regel ist nach den spezielleren ß-Regeln weiter oben anzuwenden.
242 sub ß {
243 # heiß -> heiss
244 # büß-te -> büss-te
245 $_[0] =~ s/ß
246 /ss/xg;
249 sub ß_ {
250 $_[0] =~ s/ß
251 /ss/xg;
255 # »ss-s« -> »{ss/ss-s}« (ref. -> trad. schweiz.)
257 sub ss_s {
258 # Ess=sucht -> E{ss/ss=s}sucht
259 # (Biss=spur -> Biss=spur)
260 $_[0] =~ s/ss
261 (\W+)
263 (?= [aeiouäöüy] )
264 /{ss\/ss$1s}/xg;
267 sub ss_s_ {
268 $_[0] =~ s/ss
269 (\W+)
271 (?= [aeiouäöüy] )
272 /ss/xg;
276 # »ss« -> »ß« (ref. -> trad.)
278 sub ss {
279 # biss=fest -> biß=fest
280 # esst -> eßt
281 # Hass -> Haß
282 # (Fa-desse -> Fa-desse)
283 $_[0] =~ s/ss
284 (?= (?: [b-df-hj-np-rtv-z]
285 | \W
286 | $ ) )
287 /ß/xg;
290 sub ss_ {
291 $_[0] =~ s/ss
292 (?= (?: [b-df-hj-np-rtv-z]
293 | \W
294 | $ ) )
295 /ß/xg;
299 # »xx-x« -> »{xx/xx-x}« (ref. -> trad.)
300 # (ref. -> trad. versal)
301 # (ref. -> trad. schweiz.)
303 # Buchstabe »x« ist irgendein Konsonant außer »s«.
305 sub xx_x {
306 # Bau=stoff==fir-ma -> Bau=sto{ff/ff==f}ir-ma
307 # (Griff=flä-che -> Griff=flä-che)
308 $_[0] =~ s/([b-df-hj-np-rtv-z]) \g{1} (\W+) \g{1}
309 (?= [aeiouäöüy] )
310 /{$1$1\/$1$1$2$1}/xg;
312 # Kipp=phä-no-men -> Ki{pp/pp=p}hä-no-men
313 $_[0] =~ s/([prt]) \g{1} (\W+) \g{1}
314 (?= h [aeiouäöüy] )
315 /{$1$1\/$1$1$2$1}/xg;
318 sub xx_x_ {
319 $_[0] =~ s/([b-df-hj-np-rtv-z]) \g{1} \W+ \g{1}
320 (?= [aeiouäöüy] )
321 /$1$1/xg;
323 $_[0] =~ s/([prt]) \g{1} \W+ \g{1}
324 (?= h [aeiouäöüy] )
325 /$1$1/xg;
329 sub entferne_marker {
330 # Es gilt
332 # [»Variante A«/»Variante B«] -> »Variante A«
334 # Beispiel:
336 # Dru[-cker=/ck=er<.]zeug>nis -> Dru-cker=zeug>nis
338 # Beachte, daß {.../...} bei reformierter Rechtschreibung nicht auftreten
339 # kann.
340 $_[0] =~ s/\[ (.*?) \/ .*? \]/$1/gx;
342 $_[0] =~ s/\W//g;
346 # Gebe eine Zeile aus, unter Berücksichtigung der möglichen Zeilenformate.
348 sub zeile {
349 my ($wort,
350 $ref_wort, $ref_trennung,
351 $ref_versal_wort, $ref_versal_trennung,
352 $trad_wort, $trad_trennung,
353 $trad_versal_wort, $trad_versal_trennung,
354 $trad_schweiz_wort, $trad_schweiz_trennung,
355 $kommentar) = @_;
357 # Eliminiere Wortformen, die nicht mit »wort« übereinstimmen.
358 $ref_trennung = "" if $wort ne $ref_wort;
359 $ref_versal_trennung = "" if $wort ne $ref_versal_wort;
360 $trad_trennung = "" if $wort ne $trad_wort;
361 $trad_versal_trennung = "" if $wort ne $trad_versal_wort;
362 $trad_schweiz_trennung = "" if $wort ne $trad_schweiz_wort;
364 print $wort;
365 if ($ref_trennung eq $trad_trennung
366 && length($ref_trennung)) {
367 print ";"
368 . $ref_trennung; # Feld 2
370 else {
371 print ";"
372 . "-2-"
373 . ";"
374 . (length($trad_trennung) ? $trad_trennung
375 : "-3-")
376 . ";"
377 . (length($ref_trennung) ? $ref_trennung
378 : "-4-");
380 if ($ref_trennung ne $ref_versal_trennung
381 || $trad_trennung ne $trad_versal_trennung
382 || $trad_trennung ne $trad_schweiz_trennung) {
383 if ($ref_versal_trennung eq $trad_versal_trennung
384 && ($ref_versal_trennung eq $trad_schweiz_trennung
385 || !$trad_schweiz_trennung)) {
386 if (length($ref_versal_trennung)) {
387 print ";"
388 . $ref_versal_trennung; # Feld 5
391 else {
392 print ";"
393 . "-5-"
394 . ";"
395 . (length($trad_versal_trennung) ? $trad_versal_trennung
396 : "-6-")
397 . ";"
398 . (length($ref_versal_trennung) ? $ref_versal_trennung
399 : "-7-")
400 . ";";
402 if ($trad_versal_trennung eq $trad_schweiz_trennung) {
403 print "-8-";
405 else {
406 print length($trad_schweiz_trennung) ? $trad_schweiz_trennung
407 : "-8-";
413 # Kommentare werden nur einmal für Einträge in der reformierten
414 # Schreibweise ausgegeben.
415 print " " . $kommentar if $kommentar && $wort eq $ref_wort;
417 print "\n";
421 # Hauptroutine
422 # ------------
424 while (<>) {
425 # Gebe Kommentarzeilen direkt aus.
426 if (/^ \s* \#/x) {
427 print;
428 next;
431 chop;
433 # Zerlege Zeile in ihre Bestandteile. Mögliche Formate:
435 # foobar;foo-bar # blabla
436 # foobar;foo-bar
437 # foo-bar # blabla
438 # foo-bar
440 /^ (?: \S+ ;)?
441 (\S+)
443 (\# .* )? $/x;
445 my $trennung = $1;
446 my $kommentar = defined $2 ? $2 : "";
449 # Wir konstruieren jetzt alle möglichen Wortformen - der Benutzer muß
450 # natürlich trotzdem alles kontrollieren.
452 # Die Ausgabe erfolgt unsortiert.
454 # reformierte Rechtschreibung
455 my $ref_trennung = $trennung;
457 my $ref_wort = $trennung;
458 entferne_marker($ref_wort);
460 # reformierte Rechtschreibung, Versalform
461 my $ref_versal_trennung = $trennung;
462 bindestrich_ß_1($ref_versal_trennung);
463 ß($ref_versal_trennung);
465 my $ref_versal_wort = $trennung;
466 bindestrich_ß_1_($ref_versal_wort);
467 ß_($ref_versal_wort);
468 entferne_marker($ref_versal_wort);
470 # traditionelle Rechtschreibung
471 my $trad_trennung = $trennung;
472 s_t($trad_trennung);
473 ck($trad_trennung);
474 ss($trad_trennung);
475 xx_x($trad_trennung);
477 my $trad_wort = $trennung;
478 s_t_($trad_wort);
479 ck_($trad_wort);
480 ss_($trad_wort);
481 xx_x_($trad_wort);
482 entferne_marker($trad_wort);
484 # traditionelle Rechtschreibung, Versalform
485 my $trad_versal_trennung = $trennung;
486 s_t($trad_versal_trennung);
487 ck($trad_versal_trennung);
488 bindestrich_ß_2($trad_versal_trennung);
489 ß($trad_versal_trennung);
490 xx_x($trad_versal_trennung);
492 my $trad_versal_wort = $trennung;
493 s_t_($trad_versal_wort);
494 ck_($trad_versal_wort);
495 bindestrich_ß_2_($trad_versal_wort);
496 ß_($trad_versal_wort);
497 xx_x_($trad_versal_wort);
498 entferne_marker($trad_versal_wort);
500 # traditionelle Rechtschreibung, schweizerdeutch
501 my $trad_schweiz_trennung = $trennung;
502 s_t($trad_schweiz_trennung);
503 ck($trad_schweiz_trennung);
504 bindestrich_ß_1($trad_schweiz_trennung);
505 ß_s($trad_schweiz_trennung);
506 ß($trad_schweiz_trennung);
507 ss_s($trad_schweiz_trennung);
508 xx_x($trad_schweiz_trennung);
510 my $trad_schweiz_wort = $trennung;
511 s_t_($trad_schweiz_wort);
512 ck_($trad_schweiz_wort);
513 bindestrich_ß_1_($trad_schweiz_wort);
514 ß_s_($trad_schweiz_wort);
515 ß_($trad_schweiz_wort);
516 ss_s_($trad_schweiz_wort);
517 xx_x_($trad_schweiz_wort);
518 entferne_marker($trad_schweiz_wort);
520 if ($debug) {
521 print "ref: "
522 . $ref_wort
523 . " "
524 . $ref_trennung
525 . "\n";
526 print "ref. versal: "
527 . $ref_versal_wort
528 . " "
529 . $ref_versal_trennung
530 . "\n";
531 print "trad: "
532 . $trad_wort
533 . " "
534 . $trad_trennung
535 . "\n";
536 print "trad. versal: "
537 . $trad_versal_wort
538 . " "
539 . $trad_versal_trennung
540 . "\n";
541 print "trad. schweiz: "
542 . $trad_schweiz_wort
543 . " "
544 . $trad_schweiz_trennung
545 . "\n";
546 print "->\n";
550 # Gebe Zeilen aus
551 # ---------------
553 # Wir bilden einen Hash, um Doubletten der möglichen Wortformen und
554 # Wortformen kürzer als vier Buchstaben zu entfernen.
555 my %wortformen = map { length($_) > 3 ? ($_, 1)
556 : ((), ()) }
557 ($ref_wort,
558 $ref_versal_wort,
559 $trad_wort,
560 $trad_versal_wort,
561 $trad_schweiz_wort);
563 foreach my $wort (keys %wortformen) {
564 zeile($wort,
565 $ref_wort, $ref_trennung,
566 $ref_versal_wort, $ref_versal_trennung,
567 $trad_wort, $trad_trennung,
568 $trad_versal_wort, $trad_versal_trennung,
569 $trad_schweiz_wort, $trad_schweiz_trennung,
570 $kommentar);
574 # EOF