Deutsch nach ASCII konvertieren

Deutsch nach ASCII konvertieren

am 31.07.2007 02:28:03 von das-mehdorn

Hallo!

Ich bin auf der Suche nach einem Perl-Modul bzw. vielmehr einer
Funktion, die auch durch ein Modul bereitgestellt werden darf, die
quasi wie 'encode("ascii", $string)', aber dabei deutsche Umlaute,
scharfes S etc. nach den üblichen Regeln ersetzt zu "ae", "oe", ...
"ss" etc.

Grund: Das Ziel, wo ich die Daten darstellen will, kann nur
7-Bit-Zeichen sicher transportieren bzw. verarbeiten. Und die
Ausgabe soll dabei menschenlesbar sein.


Zur Konvertierung habe ich drei Dinge gefunden:

1. Encode mit anonymer Funktion (ala perldoc Encode)

my %ascii_replace = (
196 => "Ae",
...
223 => "ss",
);

$ascii = encode(
"ascii", $string, sub {
my $c = shift;
return $ascii_replace{$c} if (defined($ascii_replace{$c}));
return "?";
}
);

Diese Variante hat den Haken, daß %ascii_replace recht umfangreich
werden könnte. Konkret will ich (deutsche) Ortsnamen umwandeln, aber
gerade in Grenznähe kommen da schon mal Akzente etc. mit hinein, die
auch berücksichtigt werden wollen.

2. Lingua::DE::ASCII

Da gibt es zwei Funktionen, to_ascii und to_latin1. Und in der
Dokumentation steht, daß sich die beiden Module quasi aufheben,
also das to_ascii offenbar einen Latin-1-kodierten String will.
Allerdings habe ich keine Lust, jedesmal meine Perl-Strings erst
nach ISO-8859-1 umzukodieren, um sie danach zu ASCII zu wandeln.

Ganz abgesehen davon: Das Modul ist wegen der Funktion to_latin1
recht komplex und fett; allerdings brauche ich die Gegenrichtung
nicht. Somit verbrate ich unnötig Platz und Ladezeit.

Allerdings muß ich wohl keinen Hash erstellen/pflegen.

3. Regex-Wirrwarr

Gefunden habe ich weiterhin eine kleine Sub, die die Ersetzung
mit einer Regex erledigt und danach gegebenenfalls verbleibende
Nicht-7-Bit-Zeichen wahlweise auch per Regex durch Fragezeichen
ersetzt oder mit tr/// wegwirft.

Ähnlich wie bei Variante 1 wird hier die Menge der Ersetzungs-Regexen
recht hoch, wenn man mehr als nur die Umlaute und das scharfe S ersetzen
will.


Alle drei Varianten haben also entscheidende Nachteile (soweit
ich das überblicke). Nun stellt sich mir die Fragen:

- Habe ich etwas übersehen?
- Gibt es das auch in "schön"?
- Wo finde ich das gegebenenfalls?
- Gibt es vielleicht ein tolles Encoding ähnlich wie ascii-ctrl,
das eine passende Ersetzung liefert?
(- Oder ist mein Problem doch so selten?)


Ach ja, fürs Protokoll: Meine Perl-Version ist 5.8.8, und
encode('MIME-Q', $string) will ich eher nicht. Auch, wenn es
vielleicht nicht die schlechteste Wahl ist.

Christoph

--
In Berlin gibt es die Pfannkuchen sowohl mit Puderzucker als auch mit
Zuckerguss. Beide Arten bekomme ich nur mit Widerwillen herunter. --
"Ein Pfannkuchen mit Puderzucker und Widerwillen, bitte..."
(Dieter Bruegmann, Volker Gringmuth)

Re: Deutsch nach ASCII konvertieren

am 31.07.2007 07:19:59 von Bjoern Hoehrmann

* Christoph 'Mehdorn' Weber wrote in de.comp.lang.perl.misc:
> Ich bin auf der Suche nach einem Perl-Modul bzw. vielmehr einer
>Funktion, die auch durch ein Modul bereitgestellt werden darf, die
>quasi wie 'encode("ascii", $string)', aber dabei deutsche Umlaute,
>scharfes S etc. nach den üblichen Regeln ersetzt zu "ae", "oe", ...
>"ss" etc.

Es wäre gut gewesen, hier gleich alle Anforderungen anzugeben, später
schreibst du ja auch von Akzenten und anderem. Text::Unidecode hat das
im Prinzip zum Ziel, wandelt "ö" allerdings in "o", nicht "oe".

> Zur Konvertierung habe ich drei Dinge gefunden:
>
>1. Encode mit anonymer Funktion (ala perldoc Encode)

Mir scheint es wäre sinnvoller das mit

%trans = ( "ä" => "ae", ... );
s/([...])/...$trans{$1}.../eg;

zu machen. Ich seh hier nicht wirklich das Problem mit dem Umfang der
Ersetzungstabelle. Wenn es um Geschwindigkeit geht, wäre es ggf. sinn-
voll, das direkt in C zu schreiben.
--
Björn Höhrmann · mailto:bjoern@hoehrmann.de · http://bjoern.hoehrmann.de
Weinh. Str. 22 · Telefon: +49(0)621/4309674 · http://www.bjoernsworld.de
68309 Mannheim · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/

Re: Deutsch nach ASCII konvertieren

am 31.07.2007 19:13:13 von Hermann Martinelli

Christoph 'Mehdorn' Weber wrote:
> Hallo!
>
> Ich bin auf der Suche nach einem Perl-Modul bzw. vielmehr einer
> Funktion, die auch durch ein Modul bereitgestellt werden darf, die
> quasi wie 'encode("ascii", $string)', aber dabei deutsche Umlaute,
> scharfes S etc. nach den üblichen Regeln ersetzt zu "ae", "oe", ...
> "ss" etc.
>
> Grund: Das Ziel, wo ich die Daten darstellen will, kann nur
> 7-Bit-Zeichen sicher transportieren bzw. verarbeiten. Und die
> Ausgabe soll dabei menschenlesbar sein.

Kommt darauf an, wie die Umgebung jetzt ist,
aber vielleicht hast Du auch die Möglichkeit,
das Ganze in Base64 zu kodieren und auf der
anderen Seite wieder zu dekodieren?

> 1. Encode mit anonymer Funktion (ala perldoc Encode)
[...]
> Diese Variante hat den Haken, daß %ascii_replace recht umfangreich
> werden könnte. Konkret will ich (deutsche) Ortsnamen umwandeln, aber
> gerade in Grenznähe kommen da schon mal Akzente etc. mit hinein, die
> auch berücksichtigt werden wollen.

Grenznähe zu Korea oder was? ;-)
Die paar Akzente, Ligaturen und Umlaute in Europa
sind doch wahrlich überschaubar.

Falls es das nicht schon gibt (dann würdest Du ja
nicht fragen, oder?) würde ich mir diesen ganzen
Kram in eine Klasse packen und fertig.
my $translator = Translator->new();
$ascii = Translator->schaffwatt($latin);

So hällst Du Dir Deinen Code sauber, falls
hier Deine Bedenken liegen.

Falls Performance das Problem sein könnte, am
besten Deine Vorschläge mal benchmarken.

> 3. Regex-Wirrwarr
>
> Gefunden habe ich weiterhin eine kleine Sub, die die Ersetzung
> mit einer Regex erledigt und danach gegebenenfalls verbleibende
> Nicht-7-Bit-Zeichen wahlweise auch per Regex durch Fragezeichen
> ersetzt oder mit tr/// wegwirft.

Zeig mal!
Ich benutze tr sehr selten und frage mich gerade, ob
man damit überhaupt 1 Zeichen (A-Umlaut) in 2 Zeichen
(Ae) umwandeln kann.
Aber wenn es geht und auch noch schnell, dann könnte
ich mit dem Wirrwarr leben.

H.M.

Re: Deutsch nach ASCII konvertieren

am 01.08.2007 16:52:40 von das-mehdorn

Hallo!

Hermann Martinelli :
> Christoph 'Mehdorn' Weber wrote:

> Kommt darauf an, wie die Umgebung jetzt ist,
> aber vielleicht hast Du auch die Möglichkeit,
> das Ganze in Base64 zu kodieren und auf der
> anderen Seite wieder zu dekodieren?

Nein, wie gesagt, es soll direkt menschenlesbar sein. Ich kippe das
quasi in einen telnet-artigen Tunnel und auf der anderen Seite wird es
direkt angezeigt. Dort habe ich keinen Einfluß auf die Anzeige, nicht
einmal auf das Charset, und das schwankt je nach Client. Daher sind nur
7Bit-Zeichen sicher, denn ASCII als Grundmenge ist überall vorhanden.


[In Klasse kapseln]
> So hällst Du Dir Deinen Code sauber, falls
> hier Deine Bedenken liegen.

Keine schlechte Idee.


>> Gefunden habe ich weiterhin eine kleine Sub, die die Ersetzung
>> mit einer Regex erledigt und danach gegebenenfalls verbleibende
>> Nicht-7-Bit-Zeichen wahlweise auch per Regex durch Fragezeichen
>> ersetzt oder mit tr/// wegwirft.
> Zeig mal!
> Ich benutze tr sehr selten und frage mich gerade, ob
> man damit überhaupt 1 Zeichen (A-Umlaut) in 2 Zeichen
> (Ae) umwandeln kann.

Ok, das war ungenau formuliert. Ersetzen wollte ich durchaus mit s///,
gerade weil es mehr Zeichen werden. Lediglich zum Herauswerfen wollte
ich tr nutzen. Also so in der Art:

s/ä/ae/g
s/ö/oe/g
[..]
tr/[:print:]/?/c;
bzw.
tr/[:print:]//cd;

Sicher kann man das tr auch mit substitute machen, aber angeblich ist
tr wesentlich flinker.

Christoph

--
[Ueber die Columbia] Wer auch immer heute Geburtstag hatte,
ich finde, ein kleineres Feuerwerk haette es auch getan.
(Adrian Knoth)

Re: Deutsch nach ASCII konvertieren

am 19.08.2007 15:53:33 von unknown

Post removed (X-No-Archive: yes)

Re: Deutsch nach ASCII konvertieren

am 20.08.2007 09:10:09 von Ferry Bolhar

Ralf Döblitz:

> s/[]äæ/ae/g;
> s/[öø]/oe/g;

In den nordischen Sprachen ist ein Ersetzen wie von dir gezeigt eher
unüblich - außerdem bliebe dann noch das "å", das auch irgendwie
ersetzt werde müsste. Daher läßt man es gleich bleiben und schreibt,
so es nicht anders möglich ist, nur "a" bzw. "o" ("æ" wird natürlich
schon durch "ae" ersetzt, aber "oe" für "ø" habe ich eigentlich noch
nicht gesehen).

LG, Ferry

--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at

Re: Deutsch nach ASCII konvertieren

am 20.08.2007 11:31:37 von Joergen Lang

ist aber normal,

J[oe|ø]rgen ;o)

Ferry Bolhar schrieb:
> Ralf Döblitz:
>
>> s/[öø]/oe/g;
>
> aber "oe" für "ø" habe ich eigentlich noch
> nicht gesehen).
>
> LG, Ferry
>

Re: Deutsch nach ASCII konvertieren

am 20.08.2007 19:49:51 von Helmut Wollmersdorfer

Christoph 'Mehdorn' Weber wrote:

> Ok, das war ungenau formuliert. Ersetzen wollte ich durchaus mit s///,
> gerade weil es mehr Zeichen werden.

Alle ca. 1.500 Latin-Zeichen von UNICODE?

Lediglich zum Herauswerfen wollte
> ich tr nutzen. Also so in der Art:

> s/ä/ae/g
> s/ö/oe/g

Wenn Dein Input utf-8 ist, dann solltest Du auch ein

use utf8;

setzen, damit solche Regexen auch mit Characters ausserhalb Latin-1
funktionieren (z.B. polnisches L mit Strich).

Weiters funktionieren obige Regexen nur zuverlässig, wenn es wirklich
UTF-8 (mit gesetztem UTF-8 Flag) ist, und wenn die Zeichen im
Input-String nicht 'decomposed' sind.

Auf die Grundform (ohne Diacritics) reduzieren kannst Du mit

use Unicode::Normalize;
my $NFD_string = NFD($string);
$NFD_string =~ s/\p{Diacritic}//g;

Gewisse Zeichen lassen sich aber nicht zerlegen, wie z.B. das polnische
L mit Strich oder das nordische O mit Strich

Ł U+0141 LATIN CAPITAL LETTER L WITH STROKE
ł U+0142 LATIN SMALL LETTER L WITH STROKE
Ø U+00D8 LATIN CAPITAL LETTER O WITH STROKE
ø U+00F8 LATIN SMALL LETTER O WITH STROKE

Dagegen hilft folgendes:

use charnames ':full';
my $new_string = q{};
for my $char (split //, $string) {
my $name = charnames::viacode(ord($char));
$name =~ s/^(.+)\sWITH\s.*/$1/;
$new_string .= chr(charnames::vianame($name));
}

> [..]
> tr/[:print:]/?/c;
> bzw.
> tr/[:print:]//cd;

Schau mal genauer in encode/decode - AFAIR kann man da eine CHECK-Option
setzen, womit das Ersatzzeichen für ungültige Character gesetzt wird.
Bei Kodierung nach ASCII müsste das automatisch das '?' sein.

Extratip:
Confusables - z.B. 'a' ist nicht gleich 'a', obwohl es gleich aussieht.
Kommt z.B. in Texten russischer Herkunft gerne vor.

Viel Spass beim UNICODE-Basteln.

Helmut Wollmersdorfer