mbstring-Funktionen/ UTF-8 in PHP
wahsaga
- php
'nabend,
hat hier jemand erfahrung mit den mbstring-funktionen von PHP?
mich würde folgendes interessieren:
1. zum "Function Overloading Feature", mit dem man einige der nicht multi-byte-fähigen (string-)funktionen von PHP mit deren mbstring-pendants "überlagern" kann, steht im manual:
"It is not recommended to use the function overloading option in the per-directory context, because it's not confirmed yet to be stable enough in a production environment and may lead to undefined behaviour."
ist dem wirklich (noch) so? d.h., fahre ich besser, wenn ich an allen stellen im script wirklich explizit die mbstring_funktionen statt der "normalen" verwende - oder ist diese option inzwischen "stable enough", dass man sie entsprechend setzen und dann im script weiterhin die "normalen" funktionsnamen stehen lassen könnte?
2. was ist mit den string-funktionen, die unter an dieser stelle _nicht_ genannt werden, wie beispielsweise trim() oder auch preg_replace() - sind die "von natur aus" multi-byte-fähig, oder muss/sollte ich hier mit komplikationen rechnen?
wäre nett, wenn mich jemand an seinen erfahrungen diesbezüglich teilhaben lassen könnte.
gruß,
wahsaga
你好 wahsaga,
[...]
2. was ist mit den string-funktionen, die unter an dieser stelle
_nicht_ genannt werden, wie beispielsweise trim() oder auch
preg_replace() - sind die "von natur aus" multi-byte-fähig, oder
muss/sollte ich hier mit komplikationen rechnen?
Von trim() habe ich keine Ahnung, aber die manpage zur libpcre, die auch von
PHP benutzt wird, sagt in pcrecompat:
1. PCRE does not have full UTF-8 support. Details of what it does have are
given in the section on UTF-8 support in the main pcre page.
Weiter steht da:
UTF-8 SUPPORT
Starting at release 3.3, PCRE has had some support for character strings encoded in the UTF-8 format. For release 4.0 this has been
greatly extended to cover most common requirements.
In order process UTF-8 strings, you must build PCRE to include UTF-8 support in the code, and, in addition, you must call pcre_com-
pile() with the PCRE_UTF8 option flag. When you do this, both the pattern and any subject strings that are matched against it are
treated as UTF-8 strings instead of just strings of bytes.
If you compile PCRE with UTF-8 support, but do not use it at run time, the library will be a bit bigger, but the additional run time
overhead is limited to testing the PCRE_UTF8 flag in several places, so should not be very large.
The following comments apply when PCRE is running in UTF-8 mode:
1. When you set the PCRE_UTF8 flag, the strings passed as patterns and subjects are checked for validity on entry to the relevant
functions. If an invalid UTF-8 string is passed, an error return is given. In some situations, you may already know that your strings
are valid, and therefore want to skip these checks in order to improve performance. If you set the PCRE_NO_UTF8_CHECK flag at compile
time or at run time, PCRE assumes that the pattern or subject it is given (respectively) contains only valid UTF-8 codes. In this
case, it does not diagnose an invalid UTF-8 string. If you pass an invalid UTF-8 string to PCRE when PCRE_NO_UTF8_CHECK is set, the
results are undefined. Your program may crash.
2. In a pattern, the escape sequence \x{...}, where the contents of the braces is a string of hexadecimal digits, is interpreted as a
UTF-8 character whose code number is the given hexadecimal number, for example: \x{1234}. If a non-hexadecimal digit appears between
the braces, the item is not recognized. This escape sequence can be used either as a literal, or within a character class.
3. The original hexadecimal escape sequence, \xhh, matches a two-byte UTF-8 character if the value is greater than 127.
4. Repeat quantifiers apply to complete UTF-8 characters, not to individual bytes, for example: \x{100}{3}.
5. The dot metacharacter matches one UTF-8 character instead of a single byte.
6. The escape sequence \C can be used to match a single byte in UTF-8 mode, but its use can lead to some strange effects.
7. The character escapes \b, \B, \d, \D, \s, \S, \w, and \W correctly test characters of any code value, but the characters that PCRE
recognizes as digits, spaces, or word characters remain the same set as before, all with values less than 256.
8. Case-insensitive matching applies only to characters whose values are less than 256. PCRE does not support the notion of "case"
for higher-valued characters.
9. PCRE does not support the use of Unicode tables and properties or the Perl escapes \p, \P, and \X.
Du musst also deine preg_*-Pattern mit dem u-Flag erweitern
(preg_match('/.../u',$txt)) und die oben genannten Hinweise beachten.
再见,
CK
你好 wahsaga,
- was ist mit den string-funktionen, die unter an dieser stelle
_nicht_ genannt werden, wie beispielsweise trim() [...]
Ich habe mir jetzt mal den Sourcecode von trim() angesehen. Diese Funktion
ist _nicht_ multibyte-faehig, sie entfernt nur \x20\n\r\t\v\0 links und/oder
rechts vom String. Es werden keinerlei Unicode-Whitespaces entfernt.
Inwieweit diese Bytemuster Innerhalb von UTF-32- oder UTF-16-Strings
auftreten koennen, kann ich dir nicht sagen, in UTF-8 ist das insofern
nicht von belang, als das keine Zeichen “kaputt” gemacht werden (weil
saemtliche zeichen, die entfernt werden, unterhalb von 127 liegen -- und
in diesem Teil ist UTF-8 mit ASCII gleichzusetzen).
再见,
CK
'nabend Christian,
danke für deine ausführungen.
Inwieweit diese Bytemuster Innerhalb von UTF-32- oder UTF-16-Strings
auftreten koennen, kann ich dir nicht sagen, in UTF-8 ist das insofern
nicht von belang, als das keine Zeichen “kaputt” gemacht werden (weil
saemtliche zeichen, die entfernt werden, unterhalb von 127 liegen -- und
in diesem Teil ist UTF-8 mit ASCII gleichzusetzen).
d.h., trim() ist "sicher", so lange ich nur utf-8 verwende, OK.
hatte mir als alternative überlegt, dann stattdessen ebenfalls preg_replace zu nutzen, und whitespace (über \s) am stringanfang/-ende durch leerstring zu ersetzen.
gruß,
wahsaga
你好 wahsaga,
Inwieweit diese Bytemuster Innerhalb von UTF-32- oder UTF-16-Strings
auftreten koennen, kann ich dir nicht sagen, in UTF-8 ist das insofern
nicht von belang, als das keine Zeichen “kaputt” gemacht werden (weil
saemtliche zeichen, die entfernt werden, unterhalb von 127 liegen -- und
in diesem Teil ist UTF-8 mit ASCII gleichzusetzen).d.h., trim() ist "sicher", so lange ich nur utf-8 verwende, OK.
Wenn du keinen Wert darauf legst, dass Unicode-Whitespaces entfernt
werden: ja.
hatte mir als alternative überlegt, dann stattdessen ebenfalls
preg_replace zu nutzen, und whitespace (über \s) am stringanfang/-ende
durch leerstring zu ersetzen.
In den Anmerkungen von libpcre steht, dass \s nur auf die Whitespaces <
256 zutrifft, also auch _nicht_ auf Unicode-Whitespaces.
再见,
CK
hi,
Wenn du keinen Wert darauf legst, dass Unicode-Whitespaces entfernt
werden: ja.
...
In den Anmerkungen von libpcre steht, dass \s nur auf die Whitespaces <
256 zutrifft, also auch _nicht_ auf Unicode-Whitespaces.
ähm ... was es in unicode denn noch für whitespaces > 255 gibt, ist mir im moment noch gar nicht bewusst :-)
gruß,
wahsaga
你好 wahsaga,
Wenn du keinen Wert darauf legst, dass Unicode-Whitespaces entfernt
werden: ja.
...
In den Anmerkungen von libpcre steht, dass \s nur auf die Whitespaces <
256 zutrifft, also auch _nicht_ auf Unicode-Whitespaces.ähm ... was es in unicode denn noch für whitespaces > 255 gibt, ist mir
im moment noch gar nicht bewusst :-)
Molily hatte netterweise mal eine Liste gemacht und mir zukommen lassen:
0x20, 0xA0, 0x2000 - 0x200B und 0x2028 - x202F sind Leerzeichen.
再见,
CK
Hallo,
ähm ... was es in unicode denn noch für whitespaces > 255 gibt, ist mir im moment noch gar nicht bewusst :-)
Molily hatte netterweise mal eine Liste gemacht und mir zukommen lassen:
0x20, 0xA0, 0x2000 - 0x200B und 0x2028 - x202F sind Leerzeichen.
Strenggenommen sind nur U+2000 bis U+200B Leerzeichen im eigentlichen Sinne, U+2028 bis U+202F sind »Formatting characters«. Wenn man die wegschneidet, sollte man z.B. auch U+200C bis U+200F entfernen. Formatting characters sind (meiner Vermutung nach) nicht notwendigerweise irrelevante Zeichen, wenn sie am Anfang bzw. Ende eines Strings stehen. Vielleicht gibt es Fälle, in denen ein solches Zeichen durchaus seinen Sinn an diesen Stellen hat, dazu kenne ich die vielen von Unicode repräsentierten Schriftsysteme nicht.
Darüber hinaus gibt es wahrscheinlich unzählige weitere Steuerzeichen, die man für gewöhnlich nicht gerne im String haben will. Hängt letztlich wohl davon ab, welche Aufgabe das trim() erfüllen soll.
Mathias
Hallo!
wäre nett, wenn mich jemand an seinen erfahrungen diesbezüglich teilhaben lassen könnte.
Eigene Erfahrungen habe ich auf deisem Feld leider noch nicht, irgendwie ist mir das ganze Thema noch etwas suspekt.
Ne kleine Diskussion zur PHP 5.1 Roadmap:
http://www.zend.com/lists/php-dev/200410/msg00344.html
(wenn ich mich richtig erinnere wurde verbesserter, evtl. nativer Unicode-Support auf die 5.2 verschoben ;-))
Evtl. kannst Du auch mit http://de3.php.net/iconv arbeiten?
Noch eine Diskussion zum Thema mb* Funktionen:
http://www.zend.com/lists/php-dev/200408/threads.html#00661
Und noch eine kleine Präsentation:
http://talks.php.net/show/wereldveroverend-ffm2004/
Grüße
Andreas