Stringlänge und utf-8-Zeichen
Elya
- php
0 Axel Richter0 Elya
0 molily0 Elya
Hallo,
ich versuche, kyrillische utf-8-Zeichenketten nach bestimmten definierten Regeln in lateinische umzusetzen. Dazu schreibe ich die Zeichen zunächst einzeln in ein Array. Da mir str_split() und PHP5 noch nicht zur Verfügung steht, habe ich folgendes gebastelt:
for ($i=0;$i<strlen($string);$i+=2){
$substr = substr($string,$i,2); // ein unicode-Zeichen besetzt 2
//Zeichen - deshalb in Zweierschritten
array_push($kyr_string,$substr);
}
Das entstandene Array wird mit Hilfe einer Library (auch Arrays, Regeln und Ausnahmen) in andere Zeichen umgesetzt. Der Haken ist der Zweierschritt in dem substr-Ausdruck oben. Sind nämlich z.B. einfache lateinische Zeichen im String enthalten, für die strlen($zeichen) == 1
gilt, zerhackt die obige Schleife die weiteren Zeichen (bzw packt sie auch in Zweierpäckchen), so daß die Umsetzung später an dieser Stelle abbricht.
Einigermaßen verständlich?
Ich habe versucht, utf8_encode()
auf die Zeichenkette anzuwenden, aber das hat keinen Effekt. Das größte Problem bei der Sache ist vermutlich mein mangelndes Basiswissen über den Aufbau von Unicode ;-) - hat jemand eine Idee, wie ich ganz am Anfang schon die nicht-kyrillischen Zeichen aus dem String fischen und separat behandeln kann?
Möglicherweise ist das Ganze mit regulären Ausdrücken weit eleganter zu lösen, aber die sind für mich leider immer noch ein schwarzes Loch.
Danke fürs Nachdenken.
Gruß aus Köln-Ehrenfeld,
Elya
Hallo,
ich versuche, kyrillische utf-8-Zeichenketten nach bestimmten definierten Regeln in lateinische umzusetzen.
Der Haken ist der Zweierschritt in dem substr-Ausdruck oben.
Ja, wie viele octets ein Zeichen in UTF-8 hat, erkennst Du an den hochwertigsten bits des Startzeichens http://rfc.sunsite.dk/rfc/rfc3629.html
...
Char. number range | UTF-8 octet sequence
(hexadecimal) | (binary)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
...
Du musst also octet für octet (byte für byte) aus dem String nehmen und prüfen.
Steht vorn eine 0, dann ist das octet das Zeichen.
Steht vorn 110, dann besteht das Zeichen aus 2 octets.
usw...
Das gilt allerdings nur für UTF-8. Unicode kann auch in anderen encodings vorliegen http://www.unicode.org/faq/utf_bom.html.
viele Grüße
Axel
Hallo Axel,
danke für Deine Antwort.
Ja, wie viele octets ein Zeichen in UTF-8 hat, erkennst Du an den hochwertigsten bits des Startzeichens http://rfc.sunsite.dk/rfc/rfc3629.html
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
...Du musst also octet für octet (byte für byte) aus dem String nehmen und prüfen.
irgendwie habe ich geahnt, daß es nicht ganz trivial ist ;-) Ich probiere das heute abend mal aus, mal sehen, wie ich die octets aus dem String gefummelt bekomme.
Gruß aus Köln-Ehrenfeld,
Elya
你好 Elya,
irgendwie habe ich geahnt, daß es nicht ganz trivial ist ;-) Ich probiere
das heute abend mal aus, mal sehen, wie ich die octets aus dem String
gefummelt bekomme.
Ein Octet ist bei PHP in jedem Fall ein Byte und damit ein “Buchstabe”. Es
ist also trivial, einzelne Octets zu betrachten, substr($str,$pos,1) reicht
da aus, bzw. bei PHP geht ja auch $str{$pos}. Ueberpruefen, um welche
Art Zeichen es sich handelt, kannst du dann recht einfach mit
Bit-Operationen:
if(ord($str{$pos}) < 0x80) {
# ein Zeichen lang
}
else if(ord($str{$pos}) < 0x2c) {
# illegale UTF-8-Sequenz, dieser Werte-Bereich kann nicht
# auftreten als Start-Sequenz
}
else if(ord($str{$pos}) < 0xe0) {
# zwei Byte lang
}
else if(ord($str{$pos}) < 0xf0) {
# drei Byte lang
}
else if(ord($str{$pos}) < 0xf8) {
# vier Byte lang
}
# Support fuer 6-Byte-UTF8, wie es im ISO/IEC beschrieben ist
else if(ord($str{$pos}) < 0xfc) {
# fuenf Byte lang
}
else if(ord($str{$pos}) < 0xfe) {
# 6 Byte lang
}
else {
# illegale UTF-8-Sequenz, dieser Werte-Bereich kann nicht
# auftreten als Start-Sequenz
}
Ist allerdings nicht getestet, sollte aber funktionieren.
再见,
克里斯蒂安
Hallo,
Falls die Multibyte-String-Extension zur Verfügung steht - was allerdings eher selten der Fall ist - kann man einfach http://de2.php.net/manual/de/function.mb-substr.php verwenden.
Mathias
Hallo Mathias,
Falls die Multibyte-String-Extension zur Verfügung steht - was allerdings eher selten der Fall ist - kann man einfach http://de2.php.net/manual/de/function.mb-substr.php verwenden.
da ich einen guten Draht zu meinem Webserveradmin habe, steht es mir erstaunlicherweise zur Verfügung - das probiere ich auch heute abend aus. Danke Dir!
Gruß aus Köln-Ehrenfeld,
Elya