2013-02-18 6 views
7

Warum Wörter folgende js Code:Bug in PHP Preg-Engine: look-um Unicode-Ausgabe

"آرد@".replace(/(?=.)/g,'!'); // returns: ""!آ!ر!د"" 

Aber seine PHP-Äquivalent gibt '!�!�!�!�!�!�'?

preg_replace('/(?=.)/u', '!', 'آرد'); //returns '!�!�!�!�!�!�' 

Dies funktioniert nur in 4.3.5 - 5.0.5, 5.1.1 - 5.1.6 Versionen.

Siehe: http://3v4l.org/jrV0W

+0

Was ist das @ tun in der PHP-Version? Sollte es nicht auch "/(?=.)/" sein? Ich frage aufrichtig, wie ich das vorher nicht gesehen habe. – kufudo

+1

'@' ist ungültiges Trennzeichen. Überprüfen Sie die Trennzeichen-Seite von [PHP] (http://www.php.net/manual/en/regexp.reference.delimiters.php). – hjpotter92

+2

@BackinaFlash Es ist gültig! – PHPst

Antwort

1

Nach einigen Tests jetzt denke ich, es gibt einen Fehler in der PREG-Engine. Die erste drei Zeilen Ausgabe was erwartet, aber die vierte Zeile ist fehlerhaft.

<?php 
echo preg_replace('/./'  , '#', 'آرد') . PHP_EOL; //✓ 
echo preg_replace('/./u'  , '#', 'آرد') . PHP_EOL; //✓ 
echo preg_replace('/(?=.)/' , '#', 'آرد') . PHP_EOL; //✓ 
echo preg_replace('/(?=.)/u' , '#', 'آرد') . PHP_EOL; //✗ 
echo preg_replace('/(?=\pL)/' , '#', 'آرد') . PHP_EOL; //? 
echo preg_replace('/(?=\pL)/u', '#', 'آرد') . PHP_EOL; //? 

heraus gesetzt:

###### 
### 
#�#�#�#�#�#� 
#�#�#�#�#�#� 
#آ#ر#د 
#آ#ر#د 
+0

Es gibt keine Fehler, tat hast du meine antwort gelesen? Ich erkläre, warum die Linie mit dem Punkt nicht funktioniert –

+0

@TomSarduy Wie Sie in meinem Beispiel sehen '/./ u' funktioniert, wenn es in einen Rundum-Look platziert. – PHPst

4

Wenn Sie einfach den /u Modifikator hinzufügen, wird das Muster soll als utf-8 behandelt werden. Das zweite Beispiel funktioniert, weil:

  1. Seit PHP 5.1 können Sie \p{L} verwenden, die übersetzt werden können: „ist jede Art von Brief von jeder Sprache.“
  2. Zusätzlich zu der Standardnotation, \ p {L}, Java, Perl, PCRE und jetzt PHP können Sie die Kurzschrift verwenden \pL. Die Kurzschrift funktioniert nur mit Unicode-Eigenschaften aus einem Buchstaben.

UPDATE: Warum preg_replace('/(?=.)/u', '!', 'آرد'); //returns '!�!�!�!�!�!�'??

Wie @MarkFox sagt, der Grund ist, weil im Rahmen der preg_replace() es ein Byte pro Zeichen und die Zeichen setzt voraus, Sie "RegExing" sind multibyte . Deshalb hat Ihre Ersetzungsausgabe die doppelte Übereinstimmung, die Sie erwarten würden. Sie entspricht jedem Byte jedes Zeichens (was zwei Byte ergibt) Unicode character properties, damit das funktioniert.

Was ist mit diesem seltsamen Symbol?

Wenn Sie sehen, dass „weird quadratisches Symbol mit einem Fragezeichen in“ anders als Ersatz CHARACTER bekannt, dass in der Regel ein Indikator, dass Sie ein Byte im Bereich von 80-FF haben (128-255) und die System versucht, es in UTF-8 zu rendern.

Das gesamte Byte-Bereich für Single-Byte-Zeichen in UTF-8 ungültig ist, aber alle sind sehr häufig in der westlichen Kodierungen wie ISO-8859-1.

+2

Die Antwort erklärt, warum \ pL mit preg_replace arbeitet. Der Grund der Punkt '.' Metazeichen fehlgeschlagen ist, weil im Kontext von Preg_replace es ein Byte pro Zeichen annimmt und die Zeichen, die Sie RegExing sind, Multibyte sind. Das ist der Grund, warum Ihre Ersetzungsausgabe die doppelten Übereinstimmungen hat, die Sie erwarten würden. Sie entspricht jedem Byte jedes Zeichens (von dem ich folge, dass es zwei Bytes sind). –

+0

@PHPst: MarkFox ist absolut richtig, in der Tat wird das ein Teil meiner Antwort sein: D –

+0

@PHPst: Was ist nicht wahr? Ich denke, alles ist da –