3 # :Copyright: © 2016 Günter Milde.
4 # Released without warranty under the terms of the
5 # GNU General Public License (v. 2 or later)
8 # umformatierung.py: Wandlung zwischen Lang- und Kurzformat der Wortliste(n)
9 # ==========================================================================
13 Wandlung zwischen Lang- und Kurzformat der Wortliste(n)
15 Die Eingabedateien werden in eine Liste gelesen, ggf. gewandelt, sortiert
16 und in die Standardausgabe, eine oder mehrere Dateien geschrieben.
18 Das spezielle Argument '-' steht für die Standardeingabe::
20 umformatierung.py -k wortliste > wlst
22 umformatierung.py neu.todo wlst-* > wortliste
24 Mit der Option ``--split`` kann die Aufteilung in Einzeldateien erzwungen
27 umformatierung.py -k langeintraege --split -o wlst
29 erzeugt die Dateien ``kurz_a`` bis ``kurz_z``.
34 import optparse
, sys
, os
, codecs
, re
36 from wortliste
import (WordEntry
, ShortEntry
,
37 ableitung1901
, sortkey_duden
)
38 from split_wortliste
import split_a_z
, write_a_z
41 # Wandeln einer Folge von Zeilen mit Wortliste-Einträgen
42 # vom Langformat ins Kurzformat oder (mit ``machskurz``) andersrum.
44 # >>> from umformatierung import convert_lines
45 # >>> for line in convert_lines([u'# Toll', u'Diens-te']): print unicode(line)
47 # Dienste;-2-;Dien-ste;Diens-te
49 # Da 3-buchstabige Wörter fehlen, sollte Biß automatisch ergänzt werden
50 # >>> for line in convert_lines([u'Biss;-2-;-3-;Biss;Biss'], long2short=True):
51 # ... print unicode(line)
52 # Biss;-2-;Biss;Biss;Biss
53 # >>> for line in convert_lines([u'Biss;-2-;Biss;Biss;Biss']):
54 # ... print unicode(line)
55 # Biss;-2-;-3-;Biss;Biss
57 # Da 3-buchstabige Wörter fehlen, sollte Fuß automatisch ergänzt werden
58 # >>> for line in convert_lines([u'Fuss;-2-;-3-;-4-;Fuss'], long2short=True):
59 # ... print unicode(line)
60 # -1-;-2-;Fuss;Fuss;Fuss
61 # >>> for line in convert_lines([u'-1-;-2-;Fuss;Fuss;Fuss']):
62 # ... print unicode(line)
63 # Fuss;-2-;-3-;-4-;Fuss
66 # >>> for line in convert_lines([u'Boss;Boss # en.']): print unicode(line)
68 # >>> for line in convert_lines([u'Boss;Boss # en.'], long2short=True): print unicode(line)
71 # Alternative Langformen
72 # ----------------------
74 # Die Kurzform kann einen oder mehrere Lang-Einträge ergeben:
76 # >>> for line in convert_lines([u'Mas-se']): print unicode(line)
78 # >>> for line in convert_lines([u'Ma-ße']): print unicode(line)
80 # Masse;-2-;-3-;-4-;-5-;Ma-sse;Mas-se;Mas-se
82 # Regelmäßig ableitbare Felder/Einträge werden in der Kurzform zusammengefaßt:
84 # >>> for line in convert_lines([u'Passstrasse;-2-;-3-;-4-;-5-;Pass=stra-sse;Pass=stras-se;Pass=stras-se',
85 # ... u'Passstraße;-2-;-3-;Pass=stra-ße',
86 # ... u'Paßstraße;-2-;Paß=stra-ße;-4-',
87 # ... ], long2short=True):
88 # ... print unicode(line)
92 # In der Langform werden Alternativen in ein Feld geschrieben:
94 # >>> for line in convert_lines([u'Mas-se', u'Ma-ße']):
95 # ... print unicode(line)
96 # Masse;-2-;Mas-se;Mas-se;-5-;[Mas-se/Ma-sse];Mas-se;Mas-se
99 # Sind die Alternativen bereits in der Quelle, bleiben sie in der Kurzform
102 # >>> ml = [u'Masse;-2-;Mas-se;Mas-se;-5-;Ma[-s/s-]se;Mas-se;Mas-se',
104 # >>> for line in convert_lines(ml, long2short=True):
105 # ... print unicode(line)
106 # Mas-se;Mas-se;Mas-se;Ma[-s/s-]se
107 # Ma-ße;Ma-ße;-3-;-4-;-5-
109 # Zurück in die Langform:
111 # >>> for line in convert_lines([u'Mas-se;Mas-se;Mas-se;Ma[-s/s-]se',
112 # ... u'Ma-ße;Ma-ße;-3-;Ma[-s/s-]se']):
113 # ... print unicode(line)
114 # Masse;-2-;Mas-se;Mas-se;-5-;Ma[-s/s-]se;Mas-se;Mas-se
119 def convert_lines(lines
, long2short
=False):
121 entries_dict
= {} # zum Zusammenfassen
125 # Dekodieren, Zeilenende entfernen
129 # Einlesen und Wandeln
130 # Zeilen mit nur einem Feld/Wort werden als ShortEntry
131 # (allgemeingültiges Muster) gelesen
133 entry
= WordEntry(line
)
134 key
= entry
.key() # Schlüssel vor dem "Wegschmeißen" holen
135 entry
= ShortEntry(entry
, prune
=False)
136 else: # einzelnes, getrenntes Wort in "de-1996"
137 entry
= ShortEntry(line
)
140 # gemeinsamer Schlüssel für zusammengehörige (Kurz)Einträge:
141 key
= key
.replace(u
'ß', u
'ss').lower()
142 key
= re
.sub(ur
'(.)\1\1(?=[aeiouyäöü])', ur
'\1\1', key
) # Kipppunkt -> Kippunkt
143 # print key, unicode(entry)
145 if key
in entries_dict
:
146 # print key, "schon da:"
147 # if entry[0]: # Grundeintrag:
148 # vertauschen klappt nicht: ergibt -1- in "kurzdatei"
149 # (entries_dict[key], entry) = (entry, entries_dict[key])
150 # evt. andersrum mergen:
151 # entry.merge(entries_dict[key], prune=False)
152 # entries_dict[key] = entry
154 entries_dict
[key
].merge(entry
, prune
=False)
155 # print 'm1', unicode(entries_dict[key])
156 # print 'm2', unicode(entry)
157 except AssertionError as e
:
158 # sys.stderr.write(unicode(e).encode('utf8')+'\n')
159 # sys.stderr.write(unicode(entry).encode('utf8')+'\n')
160 entries
.append(entry
)
162 # Spezialfall: Paß, Fuß, ... zu kurz für die wortliste
163 # (aber: Miss, Boss, ... auch in de-1901 gültig!)
164 if (len(key
) == 4 and len(entry
) == 2
165 and len(ableitung1901(entry
[0])) == 3
168 entries_dict
[key
] = entry
169 entries
.append(entry
)
170 else: # Kurzform -> Langform
171 for entry
in ShortEntry(line
).wordentries(prune
=False):
173 key
= entry
[0].lower()
176 if key
and len(key
) < 4:
178 if key
in entries_dict
: # key schon da
180 entries_dict
[key
].merge(entry
, prune
=False,
181 allow_alternatives
=True)
182 except AssertionError as e
:
183 sys
.stderr
.write(unicode(e
).encode('utf8')+'\n')
184 # entries.append(entry)
186 entries_dict
[key
] = entry
187 entries
.append(entry
)
189 for entry
in entries
:
197 if __name__
== '__main__':
201 usage
= '%prog [Optionen] Eingabedatei(en) > aus \n' + __doc__
203 parser
= optparse
.OptionParser(usage
=usage
)
204 parser
.add_option('-k', '--long2short',
205 help=u
'vom Langformat in das Kurzformat wandeln.',
206 action
="store_true", default
=False)
207 parser
.add_option('-o', '--outfile',
208 help=u
'Ausgangsdatei, Vorgabe: - (Standardausgabe)',
210 parser
.add_option('-s', '--split',
211 help=u
'Aufteilen in Dateien "OUTFILE_a" bis "OUTFILE_z".'
212 u
'Vorgabe: False (nicht splitten)',
213 action
="store_true", default
=False)
214 parser
.add_option('-u', '--unsorted', action
='store_true', default
=False,
215 help=u
'Überspringe die Sortierung.')
217 (options
, args
) = parser
.parse_args()
221 # sys.stdout mit UTF8 encoding.
222 sys
.stdout
= codecs
.getwriter('UTF-8')(sys
.stdout
)
223 # sys.stderr = codecs.getwriter('UTF-8')(sys.stderr)
225 # Einlesen in eine Liste::
227 infiles
= [sys
.stdin
if arg
=='-' else open(arg
) for arg
in args
]
228 # verschachtelte Listen entflechten: [i for lst in lsts for i in lst]
229 lines
= (line
.rstrip().decode('utf-8')
230 for infile
in infiles
for line
in infile
)
234 entries
= convert_lines(lines
, long2short
=options
.long2short
)
236 # Sortieren und Ausgeben::
238 lines
= (unicode(entry
)+u
'\n' for entry
in entries
)
240 if options
.split
is True:
241 lists
= split_a_z(lines
)
242 if options
.unsorted
is not True:
243 for l
in lists
.values():
244 l
.sort(key
=sortkey_duden
)
245 write_a_z(lists
, options
.outfile
)
247 if options
.unsorted
is not True:
248 entries
.sort(key
=sortkey_duden
)
250 if options
.outfile
== '-':
253 outfile
= codecs
.open(options
.outfile
, 'w', encoding
='utf-8')
255 output
= u
''.join(lines
)
256 outfile
.write(output
)