[Trennmuster] wiederer-*
Werner LEMBERG
wl at gnu.org
Sa Sep 24 18:57:12 CEST 2016
>> Das stimmt schon, allerdings müssen wir auch die Erzeugung von
>> gewöhnlichen TeX-Trennmustern im Auge behalten, wo es keinerlei
>> Gewichtung gibt. Wörter, wo »er<er<« auftaucht, sind meiner
>> Meinung nach zu markieren – da waren noch eine Handvoll, die hab'
>> ich jetzt ebenfalls erledigt.
>
> Handvoll ist aber sehr euphemistisch für 4656 Fälle mit
> "[=<]er[<-]".
Hehe, ich habe mich nur auf »er<er<« bezogen.
> Und eigentlich sind ja alle Trennungen im Abstand 2 vor
> höherwertigen Trennungen ungünstig, also alle 120.000 mit
> "[=<]..[-<]". Oder zumindest noch die mit anderen häufigen
> zweibuchstabigen Endungen ("en", "de", ...).
>
> Ich halte es für ungünstig, diese alle explizit zu bepunkten.
Ja.
> Sinnvoll ist das nur für die "irreführenden" Trennungen -- wenn der
> erste Teil ein anderes Wort ergibt, wie Ab<fall=er<zeu-ger
>
> Generell befürworte ich die Regel:
>
> Wenn sich die unerwünschten Trennungen aus einem einzelnen Eintrag
> über einfache Regeln gewinnen lassen, dann sollten diese Regeln in
> das Extraktionsskript.
>
> Wenn sich die unerwünschten Trennungen nur über den Abgleich mit
> anderen Einträgen gewinnen lasse (z.b. es wird ein "falsches" Wort
> gebildet), dann sollte die unerwünschte Trennung markiert werden.
Um das jetzt einmal explizit darzustellen, habe ich das angehängte
Perl-Skript geschrieben und über unsere Wortliste laufen lassen (auf
meinem Rechner braucht's ca. 20 Sekunden). Es sucht alle möglichen
ungünstigen Trennstellen (die Kriterien, was »ungünstig« nun
tatsächlich bedeutet, findet sich in den Bedingungen am Ende des
Skripts).
Das Skript findet rund 80000 Einträge, wovon aber viele nicht relevant
sind. Man könnte und sollte das ganze jetzt noch mit Wortlisten
verfeinern, um noch mehr Wörter auszuschließen, doch habe ich momentan
dazu keine Zeit. Freiwillige vor! :-)
Werner
-------------- nächster Teil --------------
#! /usr/bin/perl -w
#
use strict;
use warnings;
use utf8; # String-Literals direkt als UTF-8.
use open qw(:std :utf8);
use feature 'unicode_strings';
use Getopt::Long qw(:config bundling);
my ($opt_s, $opt_t);
GetOptions("s" => \$opt_s,
"t" => \$opt_t);
# Wir beginnen mit der Konstruktion eines Arrays, das uns für ein n-silbiges
# Wort alle möglichen Wortteile mit mehr als einer Silbe liefert. Die Werte
# im Array sind Start- und Endindizes, wobei die Trenner ebenfalls gezählt
# werden, und zusätzlich ein Flag, welches gesetzt wird, wenn der Wortteil
# genau vor der letzten Silbe endet (wir brauchen das später bei der
# Analyse). Beispiel:
#
# rei - se = fer - tig -> reise, sefer, fertig, reisefer, sefertig
# 0 1 2 3 4 5 6
#
# Das zugehörige Array für vier Silben ist also
#
# [ [0, 2, 0], [2, 4, 1], [4, 6, 0], [0, 4, 1], [2, 6, 0] ]
#
# Wir verwenden 15 als höchsten Wert für n, was für die Bearbeitung der
# »wortliste«-Datei ausreicht.
#
# Ein- und zweisilbige Wörter haben keine Zerlegung.
my @WortteilIndizes;
foreach my $n (0 .. 15) {
my @array;
foreach my $i (1 .. $n - 1) {
foreach my $j (0 .. $n - $i) {
push @array, [$j * 2,
($j + $i) * 2,
$j + $i + 1 == $n ? 1 : 0];
}
}
push @WortteilIndizes, \@array;
}
# Eine Liste aller Wörter, sortiert wie die Eingabeliste.
my @Woerter;
# Ein Hash aller Wortteile.
my %Wortteile;
sub entferne_marker {
my $arg = shift;
$arg =~ tr/-=<>·//d;
return $arg;
}
# Wir iterieren über eine Wortliste im Format der »wortliste«-Datei.
while (<>) {
next if /^#/;
chop;
# Entferne Kommentare.
s/#.*$//;
# Entferne alle Leerzeichen.
tr/ \t//d;
my @feld = split(';');
next if @feld < 2;
# reformiert: Felder 2, 4, 5, 7
# traditionell: Felder 2, 3, 5, 6
# traditionell Schweiz: Felder 2, 3, 5, 6, 8
#
# Beachte: Feld n hat Index n-1.
my $zeile = $feld[1];
$zeile = $feld[2] if defined $feld[2]
&& $feld[2] ne "-3-" && ($opt_t || $opt_s);
$zeile = $feld[3] if defined $feld[3]
&& $feld[3] ne "-4-" && !($opt_t || $opt_s);
$zeile = $feld[4] if defined $feld[4]
&& $feld[4] ne "-5-";
$zeile = $feld[5] if defined $feld[5]
&& $feld[5] ne "-6-" && ($opt_t || $opt_s);
$zeile = $feld[6] if defined $feld[6]
&& $feld[6] ne "-7-" && !($opt_t || $opt_s);
$zeile = $feld[7] if defined $feld[7]
&& $feld[7] ne "-8-" && $opt_s;
next if $zeile eq "-2-";
# Entferne spezielle Trennungen.
$zeile =~ s|\{ (.*?) / .*? \}|$1|gx;
# Entferne Doppeldeutigkeiten.
$zeile =~ s|\[ (.*?) / .*? \]|entferne_marker($1)|egx;
# Entferne Markierungen für unerwünschte Trennungen.
$zeile =~ tr/.//d;
# Wandle nach Kleinbuchstaben.
$zeile = lc($zeile);
# Wir zerlegen jetzt »zeile« in einsilbige Wortteile mit Markern
# dazwischen...
my @wortteile1 = split('([·<>=-]+)', $zeile);
my @wortteil_indizes_n = @{$WortteilIndizes[($#wortteile1 + 1) / 2]};
# ...und konstruieren alle mehrsilbigen Wortteile.
my @wortteile = map { join("",
@wortteile1[map { $_ % 2 ? () : $_ }
(${$_}[0] .. ${$_}[1])]); }
@wortteil_indizes_n;
# Wir brauchen auch Arrays mit allen Vorher- und Nachher-Markern sowie dem
# »ist letzter Marker«-Flag.
my @davor = map { my $idx = ${$_}[0] - 1;
$idx < 0 ? "" : $wortteile1[$idx] }
@wortteil_indizes_n;
my @danach = map { my $idx = ${$_}[1] + 1;
$idx > $#wortteile1 ? "" : $wortteile1[$idx] }
@wortteil_indizes_n;
my @letzter = map { ${$_}[2] } @wortteil_indizes_n;
# Füge alle Wortteile und ihre zugehörigen Daten (ganzes Wort, Marker,
# Flag ob letzter Marker des Worts) in unseren »Wortteile«-Hash ein. Die
# Werte im Hash sind Arrays, die mit neuen Werten bei Bedarf vergrößert
# werden.
while (my $wortteil = pop @wortteile) {
my $dv = pop @davor;
my $dn = pop @danach;
my $l = pop @letzter;
push @{$Wortteile{$wortteil}}, [$zeile, $dv, $dn, $l];
}
# Das ganze Wort ohne Marker.
my $wort = join("",
@wortteile1[map { $_ % 2 ? () : $_ }
(0 .. $#wortteile1)]);
push @Woerter, $wort;
}
#
# Wir iterieren jetzt über alle Wörter und schauen, welche davon identisch
# zu Wortteilen sind.
#
foreach my $wort (@Woerter) {
if (defined $Wortteile{$wort}) {
foreach my $wortteile_ref (@{$Wortteile{$wort}}) {
# Um schlechte Trennstellen zu identifizieren, brauchen wir ein paar
# Bedingungen.
my ($eintrag, $davor, $danach, $letzter_marker) = @{$wortteile_ref};
# - Ignoriere Wortteile, die selbst Komposita sind.
next if $davor =~ /(=|^$)/ && $danach =~ /(=|^$)/;
# - Ignoriere Eintrag, falls der Wortteil außer der letzten Silbe
# identisch mit dem (Teil-)Wort und der Marker an dieser Stelle »-«
# ist, damit Mehrzahlformen nicht ausgegeben werden. Wir wollen
# beispielsweise die Ausgabe von »hin-der>nis« unterdrücken, da es
# mit »hin-der>nis-se« bis auf die letze Silbe identisch ist.
next if $letzter_marker && $davor =~ /([<>=]|^$)/ && $danach =~ /-/;
# - Ignoriere Eintrag, falls der Anfangmarker ein »<« enthält, um
# Präfixe wie »ab<« oder »her<« zu vermeiden. Ditto für Einträge,
# wo der Endmarker ein »>« enthält, um Endungen wie »>keit« oder
# »>lich« zu vermeiden.
next if $davor =~ /</ && $danach =~ /([=>]|^$)/;
next if $danach =~ />/ && $davor =~ /([=<]|^$)/;
print $wort . " -> " . $eintrag . "\n";
}
}
}
# eof
-------------- nächster Teil --------------
Ein Dateianhang mit Binärdaten wurde abgetrennt...
Dateiname : schlechte-trennungen.txt.xz
Dateityp : application/octet-stream
Dateigröße : 258272 bytes
Beschreibung: nicht verfügbar
URL : <https://listi.jpberlin.de/pipermail/trennmuster/attachments/20160924/dedaca4f/attachment.obj>
Mehr Informationen über die Mailingliste Trennmuster