2009-05-26 12 views
7

Ich habe eine MySQL-Tabelle mit 120.000 Zeilen im UTF-8-Format gespeichert. Es gibt ein Feld, Produktname, das Text mit vielen Akzenten enthält. Ich muss ein zweites Feld mit dem gleichen Namen füllen, nachdem ich es in ein URL-freundliches Formular (ASCII) umgewandelt habe.iconv gibt "Illegal Character" mit smarten Zitaten - wie man sie los wird?

Da PHP nicht direkt behandeln UTF-8, ich bin mit:

 
$value = iconv ('UTF-8', 'ISO-8859-1', $value); 

den Namen ISO-8859-1 zu konvertieren, durch eine massive strstr Anweisung gefolgt jede akzentuierte Zeichen zu ersetzen durch sein akzentfreies Äquivalent (à wird zum Beispiel zu a).

jedoch die ursprünglichen Textnamen mit typografischen Anführungszeichen eingegeben wurden, und iconv Drosseln, wenn es über einen kommt - ich:

 
Unknown error type: [8] 

iconv() [function.iconv]: Detected an illegal character in input string 

loszuwerden, die typografischen Anführungszeichen zu erhalten, bevor iconv verwenden, ich habe versucht, mit drei Aussagen wie:

 
$value = str_replace('’', "'", $value); 

(â € ™ ist der Rohwert einer UTF-8-Smart-Apostroph)

Da die Textdatei ist so lang, weil dieser str_replace des th Das Skript, um jedes Mal auszumerzen.

  1. Was ist der schnellste Weg, um die typografischen Anführungszeichen (oder alle ungültigen Zeichen) aus einem UTF-8-String in Streife aus, vor iconv läuft?

  2. Oder gibt es eine einfachere Lösung für dieses ganze Problem? Was ist der schnellste Weg, um einen Namen mit vielen Akzenten in UTF-8 in einen Namen ohne Akzente, richtig geschrieben, in ASCII zu konvertieren?

+2

Haben Sie versucht, iconv() '// TRANSLIT Fähigkeit aus? Es sollte akzentuierte Zeichen in ihre lesbaren ASCII-Äquivalente konvertieren. – ceejayoz

+0

Ich schaue mir die Dokumentation an, aber ich sehe nicht, wie es helfen wird - wenn iconv() bereits an einem schlauen Zitat erstickt, wird es dann nicht noch ersticken, wenn ich // TRANSLIT benutze? –

+0

Dies ist mehr für Ihre "massive strstr Aussage" - deshalb habe ich einen Kommentar statt einer Antwort gemacht. – ceejayoz

Antwort

2

Was meinst du mit "Link-freundlich"? Nur so macht es Sinn, da der Text zwischen <a>...</a> Tags alles sein kann, ist eigentlich "URL-freundlich", ähnlich wie die URLs von SO, wo alles in [a-z-] konvertiert wird.

Wenn Sie das vorhaben, benötigen Sie eine Transliterationsbibliothek, keine Zeichensatzkonvertierungsbibliothek. (Ich hatte kein Glück, iconv() zu bekommen, um die Arbeit in der Vergangenheit zu machen, aber ich habe es schon lange nicht mehr versucht.) Es gibt eine Beta-PHP-Erweiterung translit, die probably does the job ist.

Wenn Sie Ihrer PHP-Installation keine Erweiterungen hinzufügen können, müssen Sie nach einer PHP-Bibliothek suchen, die das Gleiche tut. Ich habe es nicht benutzt, aber die PHP UTF-8 Bibliothek implementiert eine utf8_to_ascii Bibliothek, von der ich annehme, dass sie so etwas wie benötigt.

(Auch wenn iconv() fehlschlägt, wie Sie sagten, bedeutet dies, dass Ihre Eingabe nicht wirklich gültig UTF-8 ist, so dass keine Menge des Ersetzens gültig UTF-8 mit etwas anderes wird das Problem helfen. Ich kann das zurücknehmen: Wenn ephemient's answer korrekt ist, kann der iconv Fehler, den Sie sehen, sehr gut sein, weil es keine direkte Darstellung des Zeichens im Zielzeichensatz gibt. Also, vergiss es.)

+0

Ich habe die Frage geändert, um URL-freundlich zu lesen. Ich kann PHP keine Erweiterungen hinzufügen. Ich habe die von Ihnen vorgeschlagene Transliterationsbibliothek überprüft, aber sie war etwa 35% langsamer als meine ursprüngliche Lösung. –

0

Haben Sie in Betracht gezogen, MySQL zu verwenden REPLACE String-Funktion, um die störenden Strings in Apostrophe oder was auch immer zu ändern? Sie können möglicherweise den zu ersetzenden Teil, z. mit CONCAT auf CHAR Anrufe ...

+0

Ich begann mit str_replace, um die störenden Strings zu ersetzen, aber es verlangsamt das Skript zu sehr ($ value = str_replace ('' ',' '', $ value); wo ist die Asci-Darstellung der verletzendes intelligentes einfaches Zitat). Kannst du klarstellen, was du mit CONCAT auf CHAR-Calls meinst? –

+0

Ich schlug vor, REPLACE in SQL auszuführen und CONCAT (CHAR (...), ... zu verwenden, um die Teilzeichenfolge Byte für Byte zu ersetzen. –

6

Glibc (und das GNU libiconv) supports//TRANSLIT und //IGNORE Suffixen.

So unter Linux, funktioniert dies ganz gut:

 
$ echo $'\xe2\x80\x99' 
’ 
$ echo $'\xe2\x80\x99' | iconv -futf8 -tiso8859-1 
iconv: illegal input sequence at position 0 
$ echo $'\xe2\x80\x99' | iconv -futf8 -tiso8859-1//translit 
' 

Ich bin nicht sicher, was iconv im Einsatz von PHP ist, aber die Dokumentation impliziert, dass //TRANSLIT und //IGNORE wird es auch funktionieren.