Textdatei: Groß-/Kleinschreibung von Umlauten ändern
Hans
- perl
Hi,
ich stehe vor dem Problem, dass ich eine Textdatei zeilenweise einlesen und mit einer Eingabe vergleichen muss und Groß-/Kleinschreibung nicht berücksichtigt werden soll.
Da use locale und /i bei Strato scheinbar nicht funktionieren, muss ich wohl leider einen anderen Weg finden. Ich hab' dafür jetzt einfach lc() verwendet. Bekanntermaßen ändert das aber nichts an den Umlauten.
Meine Frage ist nun, wie ich die Umlaute umgewandelt bekomme. Es handelt sich um eine stinknormale Windows Textdatei, wie man sie z.B. mit Notepad erstellt. Welcher Zeichensatz liegt dem zu Grunde? Am tollsten wäre es natüerlich für mich, wenn use locale und /i funktionieren würden, dann könnte ich mir die ganze Umwandlung in Kleinschreibung sparen.
Im Moment wende ich lc() auf den request-string an, d.h. lc($request) und ich würde gerne die Umlaute durch eine Zeichenklasse ersetzen, also etwas in der Form (wobei ich in der Zeichenklasse gerne alle Umlaute hätte - groß und klein geschrieben):
$request =~ s/%c3%84/[chr(hex(c384))chr(hex(c3a4))]/eg;
Funktioniert aber leider nicht. Ich hätte gerne eine Zeichenklasse, weil ich dann auf die einzelnen Zeilen $zeile der Textdatei auch nur lc($zeile) anwenden müsste und die evtl. vorkommenden Umlaute außer Acht lassen könnte, weil sie durch die Zeichenklasse und den Ausdruck if($zeile =~ /$request/) gematcht werden würde.
Also grober Aufbau:
$request = lc($request); //Beispiel: ändeRUNG --> änderung
$request =~ s/%c3%84/[chr(hex(c384))chr(hex(c3a4))......]/eg; //[äÄöÖüÜ]nderung
$zeile = lc($zeile); //in der Textdatei gibt es eine Zeile, in der Änderung steht --> Änderung (bleibt gleich)
if($zeile =~ /$request/) //sollte dann matchen
Vermutlich ist das alles viel zu kompliziert. Bin für jeden Tip dankbar, mache jetzt schon eine ganze Weile daran rum.
Gruß,
hi,
Es handelt sich um eine stinknormale Windows Textdatei, wie man sie z.B. mit Notepad erstellt. Welcher Zeichensatz liegt dem zu Grunde?
Wenn es die Windows-Installation eines japanischen Benutzers ist - dann vermutlich eine, die japaische Zeichen darstellen kann.
Wenn es die Windows-Installation eines russischen Benutzers ist - dann ...
...
(Es fortzusetzen, schaffst du selber.)
gruß,
wahsaga
hi,
Es handelt sich um eine stinknormale Windows Textdatei, wie man sie z.B. mit Notepad erstellt. Welcher Zeichensatz liegt dem zu Grunde?
Wenn es die Windows-Installation eines japanischen Benutzers ist - dann vermutlich eine, die japaische Zeichen darstellen kann.
Wenn es die Windows-Installation eines russischen Benutzers ist - dann ...
...(Es fortzusetzen, schaffst du selber.)
gruß,
wahsaga
Ich meinte nicht Zeichensatz, sondern Zeichenkodierung und die wird wohl bei deutschen, russischen, japanischen und englischen Versionen gleich sein nehm' ich mal an.
hi,
Ich meinte nicht Zeichensatz, sondern Zeichenkodierung
Ups, ja - ich auch.
und die wird wohl bei deutschen, russischen, japanischen und englischen Versionen gleich sein nehm' ich mal an.
Nein - warum sollte sie?
gruß,
wahsaga
hi,
Ich meinte nicht Zeichensatz, sondern Zeichenkodierung
Ups, ja - ich auch.
und die wird wohl bei deutschen, russischen, japanischen und englischen Versionen gleich sein nehm' ich mal an.
Nein - warum sollte sie?
gruß,
wahsaga
Warum sollten sie nicht? Und inwiefern soll mir die Frage weiterhelfen? Selbst wenn unterschiedliche Kodierungen verwendet würden, wüsste ich trotzdem nicht, welche in meinem Fall (deutsches XP) verwendet wird. Ausserdem scheint mir in einem deutschen Forum bei einem in deutscher Sprache verfassten Beitrag die Mutmaßung, das es sich wohl um ein deutsches oder englisches Windows XP handeln wird, nicht allzu verwegen.
Da use locale und /i bei Strato scheinbar nicht funktionieren, muss ich wohl leider einen anderen Weg finden. Ich hab' dafür jetzt einfach lc() verwendet. Bekanntermaßen ändert das aber nichts an den Umlauten.
Wieso use locale und wieso scheinbar?
http://www.perl.com/doc/manual/html/pod/perllocale.html
Struppi.
Da use locale und /i bei Strato scheinbar nicht funktionieren, muss ich wohl leider einen anderen Weg finden. Ich hab' dafür jetzt einfach lc() verwendet. Bekanntermaßen ändert das aber nichts an den Umlauten.
Wieso use locale und wieso scheinbar?
http://www.perl.com/doc/manual/html/pod/perllocale.htmlStruppi.
Wieso use locale:
By default, Perl ignores the current locale. The use locale pragma tells Perl to use the current locale for some operations:
Regular expressions and case-modification functions (uc(), lc(), ucfirst(), and lcfirst()) use LC_CTYPE
Wieso scheinbar:
Ich hab's mit einem einfachen Script ausprobiert. Mit dem scheinbar wollte ich ausdrücken, das es standardmässig nicht funktioniert, vielleicht aber jemand eine Möglichkeit kennt, dies zu bewerkstelligen.
Wieso use locale:
By default, Perl ignores the current locale. The use locale pragma tells Perl to use the current locale for some operations:
Regular expressions and case-modification functions (uc(), lc(), ucfirst(), and lcfirst()) use LC_CTYPE
und du setzt auch locale?
setlocale(LC_CTYPE, "de_DE");
Wieso scheinbar:
Ich hab's mit einem einfachen Script ausprobiert. Mit dem scheinbar wollte ich ausdrücken, das es standardmässig nicht funktioniert, vielleicht aber jemand eine Möglichkeit kennt, dies zu bewerkstelligen.
ohne Fehlermeldung oder genauere Hinweise, wie du zu diesem Schluß kommst, ist das schwierig
Struppi.
Wieso use locale:
By default, Perl ignores the current locale. The use locale pragma tells Perl to use the current locale for some operations:
Regular expressions and case-modification functions (uc(), lc(), ucfirst(), and lcfirst()) use LC_CTYPEund du setzt auch locale?
setlocale(LC_CTYPE, "de_DE");Wieso scheinbar:
Ich hab's mit einem einfachen Script ausprobiert. Mit dem scheinbar wollte ich ausdrücken, das es standardmässig nicht funktioniert, vielleicht aber jemand eine Möglichkeit kennt, dies zu bewerkstelligen.
ohne Fehlermeldung oder genauere Hinweise, wie du zu diesem Schluß kommst, ist das schwierig
Struppi.
Ich habe einfach dieses Skript hier verwendet:
#!/usr/bin/perl
use locale;
print "Content-type: text/html; charset=utf-8\n\n";
$test = "Öh";
if ($test =~ /öh/i) {
print "funktioniert";
}
else {
print "funktioniert nicht";
}
Mit der Ausgabe: funktioniert nicht
Wenn ich dein setlocale(LC_CTYPE, "de_DE"); noch einfüge, bekomme ich einen Internal Server Error :-(
Wenn ich dein setlocale(LC_CTYPE, "de_DE"); noch einfüge, bekomme ich einen Internal Server Error :-(
Uiuiui, was hat Strato da bloß wieder angestelllt? ;-)
Probier mal sowas:
#!/usr/bin/perl -w
use strict;
use locale;
use POSIX qw(locale_h); # RTFM: perllocale
print "Content-Type: text/plain\r\n\r\n";
eval {
setlocale(LC_CTYPE, "de_DE");
};
if ($@) {
print "Fehlermeldung: $@\n";
} else {
print "Kein Fehler, 500 Internal Server Error war eine Halluzination\n";
}
Alexander
Probier mal sowas:
Alexander
Hm, dein Skript sagt, dass ich Halluzinationen habe.
Undefined subroutine &main::setlocale called at /home/strato/http/power/web6/51/91/51249691/htdocs/cgi-bin/test.pl line 10.
Vielen Dank für die Hilfe und Hinweise, hab' den Fehler jetzt.
Die Zeile use POSIX qw(locale_h); hat noch gefehlt.
Danke.
print "Content-Type: text/plain\r\n\r\n";
Warum "\r\n" (Hintergrund)?
Siechfred
print "Content-Type: text/plain\r\n\r\n";
Warum "\r\n" (Hintergrund)?
Weil das Testprogrämmchen aller Wahrscheinlichkeit nach auf einem Linux oder anderem Unix-Derivat laufen wird, in beiden Fällen erzeugt die Escape-Sequenz "\r\n" die geforderte Byte-Sequenz 13 und 10. Um Portabilität auf "exotische" Systeme mache ich mir bei einem Wegwerf-Script keine Sorgen.
Alexander
Wenn ich dein setlocale(LC_CTYPE, "de_DE"); noch einfüge, bekomme ich einen Internal Server Error :-(
Neben dem Tipp von ALexander, wäre vieleicht auch ein
CGI::Carp qw(fatalsToBrowser) sinnvoll (am besten in einem BEGIN Block) dann bekommst du auch eine Fehlermeldung im Browser angezeigt.
Struppi.
Wenn ich dein setlocale(LC_CTYPE, "de_DE"); noch einfüge, bekomme ich einen Internal Server Error :-(
Neben dem Tipp von ALexander, wäre vieleicht auch ein
CGI::Carp qw(fatalsToBrowser) sinnvoll (am besten in einem BEGIN Block) dann bekommst du auch eine Fehlermeldung im Browser angezeigt.Struppi.
Erklär' mich bitte nicht für völlig unfähig, aber CGI::Carp qw(fatalsToBrowser); zeigt bei mir keine Wirkung. Auch nicht, in einem BEGIN-Block.
Ich hab's nun so wie hier (http://www.perlunity.de/perl/forum/thread_013909.shtml) gemacht und bekomme beim Aufruf des Skripts von unten (das gleiche wie bei dem früheren Post) die Meldung:
Undefined subroutine &main::setlocale called at /home/strato/http/power/web6/51/91/51249691/htdocs/cgi-bin/test.pl line 10.
Das Skript:
#!/usr/bin/perl
use locale;
print "Content-type: text/html; charset=utf-8\n\n";
$SIG{__DIE__} = &dieerr;
$SIG{__WARN__} = &warnerr;
setlocale(LC_CTYPE, "de_DE");
$test = "Öh";
if ($test =~ /öh/i) {
print "funktioniert";
}
else {
print "funktioniert nicht";
}
sub warnerr{
my $msg = shift;
print $msg;
}
sub dieerr{
my $msg = shift;
print $msg;
}
Undefined subroutine &main::setlocale called at /home/strato/http/power/web6/51/91/51249691/htdocs/cgi-bin/test.pl line 10.
Vielen Dank für die Hilfe und Hinweise, hab' den Fehler jetzt.
Die Zeile use POSIX qw(locale_h); hat noch gefehlt.
Danke.
Erklär' mich bitte nicht für völlig unfähig, aber CGI::Carp qw(fatalsToBrowser); zeigt bei mir keine Wirkung. Auch nicht, in einem BEGIN-Block.
Na, da hätte noch ein use gefehlt.
Ich hab's nun so wie hier (http://www.perlunity.de/perl/forum/thread_013909.shtml) gemacht und bekomme beim Aufruf des Skripts von unten (das gleiche wie bei dem früheren Post) die Meldung:
Tut mir leid, das use hatte ich als selbstverständlich angenommen.
Der Fehler is ja nun gelöst. Aber ich bin der Meinung, dass das da auch stand, auf der Seite die ich dir verlinkt hatte. Wie auch immer.
Struppi.
Hallo.
Meine Frage ist nun, wie ich die Umlaute umgewandelt bekomme. Es handelt sich um eine stinknormale Windows Textdatei, wie man sie z.B. mit Notepad erstellt. Welcher Zeichensatz liegt dem zu Grunde? Am tollsten wäre es natüerlich für mich, wenn use locale und /i funktionieren würden, dann könnte ich mir die ganze Umwandlung in Kleinschreibung sparen.
Ich gehe davon aus, dass sowohl dein Perl Programm, als auch die Textdatei und die Benutzereingaben in ISO-8859-1 vorliegen.
Sofern du beim Schreiben deiner Programme nicht auf UTF-8 (use utf8;
) umsteigen möchtest, dürfte das encoding Pragma (ab perl 5.8.0) dir an dieser Stelle helfen, auch ohne UTF-8 von Perl's Unicode Unterstützung zu profitieren.
Indem du zu Beginn deines Programms use encoding 'iso-8859-1';
nutzt, teilst du perl mit, dass dein Programm den Zeichensatz ISO-8859-1 verwendet und alle Zeichenkettenoperationen (und Ein- und Ausgaben) sich entsprechend zu verhalten haben. Anschließend funktioniert also auch das i-Flag wie gewünscht.
Alles zusammen könnte dann z. B. so aussehen:
use encoding 'iso-8859-1', STDIN => undef, STDOUT => undef;
my $input = 'äöü';
open(my $fh, '<:encoding(iso-8859-1)', 'test.txt') || die $!;
while(<$fh>) {
chomp;
print "Die Benutzereingabe $input ist in Zeile $. ($_) enthalten.\n" if(/$input/i);
}
close($fh);
Wenn die Datei test.txt folgenden Inhalt hat...
äöü
äÖü
ÄÖÜ
... entsteht diese Ausgabe:
Die Benutzereingabe äöü ist in Zeile 1 (äöü) enthalten.
Die Benutzereingabe äöü ist in Zeile 2 (äÖü) enthalten.
Die Benutzereingabe äöü ist in Zeile 3 (ÄÖÜ) enthalten.
Um Probleme mit der Ein- und Ausgabe zu vermeiden, solltest du die Umwandlung für STDIN und STDOUT abschalten (STDIN => undef, STDOUT => undef
). Wenn die Benutzereingabe nicht in ISO-8859-1 vorliegt, musst du sie ggf. noch dekodieren (use Encode;
). Beim Öffnen der Textdatei solltest du einen PerlIO Encoding Layer verwenden, musst du aber nicht zwängsläufig.
Vermutlich ist das alles viel zu kompliziert.
Wenn du eine einfachere Lösung möchtest, kannst du auch eine simple Transliteration durchzuführen, ganz ohne Pragmas und IO-Layer:
$str =~ tr[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝ]
[àáâãäåæçèéêëìíîïðñòóôõöøùúûüý];
Schöne Grüße.