2010-03-12 19 views
11

Ich habe den folgenden PHP-Code in einer utf-8 PHP-Datei:php regex Wortgrenze Anpassung in utf-8

var_dump(setlocale(LC_CTYPE, 'de_DE.utf8', 'German_Germany.utf-8', 'de_DE', 'german')); 
var_dump(mb_internal_encoding()); 
var_dump(mb_internal_encoding('utf-8')); 
var_dump(mb_internal_encoding()); 
var_dump(mb_regex_encoding()); 
var_dump(mb_regex_encoding('utf-8')); 
var_dump(mb_regex_encoding()); 
var_dump(preg_replace('/\bweiß\b/iu', 'weiss', 'weißbier')); 

Ich mag die letzten Regex nur ganze Worte und nicht Teile von Worten zu ersetzen.

auf meinem Windows-Computer, es gibt:

string 'German_Germany.1252' (length=19) 
string 'ISO-8859-1' (length=10) 
boolean true 
string 'UTF-8' (length=5) 
string 'EUC-JP' (length=6) 
boolean true 
string 'UTF-8' (length=5) 
string 'weißbier' (length=9) 

auf dem Webserver (Linux), erhalte ich:

string(10) "de_DE.utf8" 
string(10) "ISO-8859-1" 
bool(true) 
string(5) "UTF-8" 
string(10) "ISO-8859-1" 
bool(true) 
string(5) "UTF-8" 
string(9) "weissbier" 

So die Regex funktioniert, wie ich auf Windows erwartet, aber nicht auf Linux .

Die Hauptfrage ist also, wie soll ich meine Regex schreiben, um nur an Wortgrenzen zu entsprechen?

Eine zweite Frage ist, wie ich Fenster wissen lassen kann, dass ich utf-8 in meiner PHP-Anwendung verwenden möchte.

Antwort

16

Auch im UTF-8-Modus sind Standardklassen-Kürzel wie \w und \b nicht Unicode-fähig. Sie müssen nur die Unicode-Kürzel verwenden, wie Sie gearbeitet, aber man kann es mit lookarounds statt Abwechslungen etwas weniger hässlich macht von:

/(?<!\pL)weiß(?!\pL)/u 

Beachten Sie auch, wie ich die geschweiften Klammern aus der Unicode-Klasse links Kurzarbeiter; Sie können das tun, wenn der Klassenname aus einem einzelnen Buchstaben besteht.

+1

+1 - '\ w' und' \ b' scheinen in den letzten PHP-Versionen wie erwartet zu funktionieren, aber auf sie kann man sich nicht verlassen, da sie bei der Bereitstellung Ihrer App wahrscheinlich kaputt gehen. –

+0

Beachten Sie auch die angenommene Antwort hier: http://stackoverflow.com/questions/4781898/regex-word-boundary-does-not-work-in-ut8-on-some-servers, wenn Sie die Unicode-Abkürzungen verwenden möchten! –

3

hier ist, was ich bisher gefunden habe. Durch Umschreiben dieser die Such- und Ersatzmuster wie:

$before = '(^|[^\p{L}])'; 
$after = '([^\p{L}]|$)'; 
var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', 'weißbier')); 
// Test some other cases: 
var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', 'weiß')); 
var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', 'weiß bier')); 
var_dump(preg_replace('/'.$before.'weiß'.$after.'/iu', '$1weiss$2', ' weiß')); 

ich das gewünschte Ergebnis:

string 'weißbier' (length=9) 
string 'weiss' (length=5) 
string 'weiss bier' (length=10) 
string ' weiss' (length=6) 

auf meine beiden Fenster Computer mit Apache und auf dem gehosteten Linux-Webserver läuft Apache.

Ich nehme an, es gibt einen besseren Weg, dies zu tun.

Auch möchte ich immer noch meinen Windows-Computer zu utf-8 setzen.

0

Laut this comment ist das ein Fehler in PHP. Macht die Verwendung von \W anstelle von \b einen Vorteil?

4

Vermutung war dies im Zusammenhang mit Bug #52971

PCRE-Meta-Charaktere wie \b\w nicht mit Unicode-Strings zu arbeiten.

und fixed in PHP 5.3.4

PCRE-Erweiterung: Bug # 52971 (PCRE-Meta-Zeichen nicht mit utf-8 Werk).