2009-07-04 8 views
1

Ich versuche, einige Eingabe mit Regex für eine gemischte lateinische/ideographische (Chinesisch/Japanse/Koreanisch) Volltextsuche zu sanieren/formatieren.Wie analysiert man eine lateinische/ideographische Volltextabfrage korrekt mit Regex?

Ich fand ein altes Beispiel von jemandes Versuch, eine lateinische/asiatische Sprachzeichenkette in einem Forum zu sanieren, von dem ich nicht wieder finden kann (volle Anerkennung dem ursprünglichen Autor dieses Codes).

Ich habe Probleme, den Regex-Teil der Funktion zu verstehen, insbesondere warum es scheint, die Zahlen 0, 2 und 3 anders zu behandeln als der Rest der lateinischen Zahlen 1,4-9 (im Grunde behandelt es die Zahlen 0,4-9 richtig, aber die Zahlen 0,2-3 in der Abfrage werden behandelt, als ob sie asiatische Zeichen sind).

Zum Beispiel. Ich versuche, die folgende Zeichenfolge zu sanieren:
"Hallo 1234567890 蓄積 し た abc123def"

und es wird sich in:
"hallo 1 456789 abc1 def 2 3 0 蓄 積 し た 2 3"

die korrekte Ausgabe für diesen sollte hygienisiert String sein:
„Hallo 1234567890 蓄 積 し た abc123def“

Wie Sie es richtig Leerzeichen aus den asiatischen Zeichen sehen, aber die Zahlen 0, 2, 3 sind anders als alle anderen behandelt Nummer. Jede Hilfe, warum die Regex die Zahlen 0,2 und 3 anders behandelt, wäre eine große Hilfe (oder wenn Sie einen besseren Weg kennen, um ein ähnliches Ergebnis zu erzielen)! Danke

Ich habe unten

 

function prepareString($str) { 
$str = mb_strtolower(trim(preg_replace('#[^\p{L}\p{Nd}\.]+#u', ' ', $str))); 

return trim(preg_replace('#\s\s+#u', ' ', preg_replace('#([^\12544-\65519])#u', ' ', $str) . ' ' . implode(' ', preg_split('#([\12544-\65519\s])?#u', $str, -1, PREG_SPLIT_NO_EMPTY)))); 
} 

UPDATE die Funktion enthalten: Rahmen für Klarheit Providing

ich eine Website bin Authoring in China ins Leben gerufen wird. Diese Website wird eine Suchfunktion haben und ich versuche einen Parser für die Suchanfrage zu schreiben.

Im Gegensatz zur englischen Sprache, die ein "" als Trennzeichen zwischen Wörtern in einem Satz verwendet, verwendet Chinesisch keine Leerzeichen zwischen Wörtern. Aus diesem Grund muss ich eine Suchabfrage neu formatieren, indem ich jedes chinesische Zeichen zerlege und jedes Zeichen einzeln in der Datenbank suche. Chinesische Benutzer verwenden auch lateinische/englische Zeichen für Dinge wie Markennamen, die sie zusammen mit ihren chinesischen Schriftzeichen mischen können (z. B. Ivy 牛仔 舖).

Was ich tun möchte, ist alle englischen Wörter aus den chinesischen Schriftzeichen zu trennen, und jedes chinesische Schriftzeichen mit einem Leerzeichen zu trennen.

Eine Suchanfrage könnte wie folgt aussehen: Ivy 牛仔 舖

Und ich würde es analysieren will, so dass es wie folgt aussieht: Ivy 牛 仔 舖

Antwort

0

Nach weiterer Forschung und die Hilfe von Alans Kommentaren war ich in der Lage, die richtigen regex Kombinationen zu finden, eine Abfrage Parsing-Funktion für seperating Lating und ideographic (chinesisch/japanisch) Zeichen zu erreichen, ich bin glücklich mit:

 
function prepareString($str) { 
    $str = mb_strtolower(trim(preg_replace('#[^\p{L}\p{Nd}]+#u', ' ', $str))); 
    return trim(preg_replace('#\s\s+#u', ' ', preg_replace('#\p{Han}#u', ' ', $str) . ' ' . implode(' ', preg_split('#\P{Han}?#u', $str, -1, PREG_SPLIT_NO_EMPTY)))); 
} 

$query = "米娜Mi-NaNa日系時尚館╭☆ 旅行 渡假風格 【A6402】korea拼接條紋口袋飛鼠棉" 

echo prepareString($query); //"mi nana a6402 korea 米 娜 日 系 時 尚 館 旅 行 渡 假 風 格 拼 接 條 紋 口 袋 飛 鼠 棉" 

Haftungsausschluss: Ich kann Mandarin nicht lesen und die obige Zeichenfolge wurde von einer chinesischen Website kopiert. Wenn es etwas Offensives sagt, lass es mich wissen und ich werde es entfernen.

1

Das Problem mit dem regex zu sein scheint [^\12544-\65519] . Es sieht so aus, als ob es ein Bereich ist, der durch zwei, fünfstellige Oktal-Fluchten definiert wird, aber das funktioniert nicht so.Die tatsächliche Aufteilung ist wie folgt:

\125 => octal escape for 'U' 
4 => '4' 
4 => '4' 
- 
\655 => octal escape for... (something) 
1 => '1' 
9 => '9' 

, die effektiv das gleiche wie:

[^14-\655] 

Was \655 bedeutet als die Oberseite eines Bereichs ist nicht klar, aber die Zeichenklasse entspricht nichts außer einem '1', '4' oder irgendein ASCII-Zeichen mit einem Codepunkt höher als '4' (der '9' und 'U' enthält). Es ist jedoch nicht wirklich wichtig; Der wichtige Punkt ist, dass Oktav-Fluchten maximal drei Ziffern enthalten können, was sie für Ihre Bedürfnisse ungeeignet macht. Ich schlage vor, Sie verwenden PHP \x{nnn} hexadezimale Schreibweise stattdessen.

+0

Dank Alan, ich habe versucht, \ x {nnn} wie Sie vorgeschlagen, aber ich kann nicht scheinen, Dokumentation zu finden, wie eine ganze Reihe von hexadezimalen Notation übereinstimmen. Ich kann ein einzelnes Zeichen abgleichen, aber um einen ganzen Bereich zu blockieren, kann ich nicht die Lösung finden. Irgendwelche Vorschläge? Ich habe auch versucht, die p {Latin} Notation zu verwenden, aber es gibt mir Ärger, weil es mir ähnliche Probleme gibt. zB: "hallo 1234567890 蓄積 し た abc123def" wird aufgeteilt in: "hell 1234567890 ab 23def" bei der Verwendung von preg_replace ('# \ P {Nd} \ P {Latein} #u', '', $ str) – justinl

+0

Ich bin immer noch nicht klar, was Sie zu tun versuchen. Können Sie uns die richtige Ausgabe für Ihren Testfall zeigen? Bitte bearbeiten Sie Ihre Frage und legen Sie sie dort, nicht in einem Kommentar. –

+0

Vielen Dank Alan, ich habe meine Frage aktualisiert und werde weitere Hinzufügungen/Fragen innerhalb des Hauptteils der Frage anstelle dieses Kommentarfeldes zur Verfügung stellen. – justinl

1

Ich bin nicht eingerichtet, entweder mit PHP oder Chinesisch zu arbeiten, also kann ich Ihnen keine definitive Antwort geben, aber das sollte Ihnen zumindest helfen, die Frage zu verfeinern. Wie ich es sehe, ist es im Grunde ein Vier-Stufen-Prozess:

  • von unerwünschten Zeichen wie Interpunktion loszuwerden, sie mit Leerzeichen

  • normalisieren Leerzeichen ersetzen: loszuwerden führenden und nachgestellten Leerzeichen und Zusammenbruch Läufe von zwei oder mehr Räumen zu einem Raum

  • Normalisieren Fall:

  • wo immer ein chinesisches Zeichen ist keine Großbuchstaben mit ihrem Klein Äquivalente ersetzt NEX t zu einem anderen Nicht-Leerzeichen, trennen Sie die beiden Charaktere mit einem Raum

Für die ersten drei Schritte, die erste Zeile des Codes geschrieben Sie sollte ausreichen:

$str = mb_strtolower(trim(preg_replace('#[^\p{L}\p{Nd}\.]+#u', ' ', $str))); 

Für den letzten Schritt würde ich lookarounds vorschlagen:

$str = preg_replace(
    '#(?<=\S)(?=\p{Chinese})|(?<=\p{Chinese})(?=\S)#u', 
    ' ', $str); 

, dass ein Raum an einer beliebigen Stelle einfügen sollte, wo das nächste Zeichen Chinese und das vorherige Zeichen ist nicht Leerzeichen oder vorherige Zeichen ist Chinesisch und die nächste Zeichen ist kein Leerzeichen.

+0

Ich habe versucht, Ihre Lookaround-Methode zu verwenden, aber als ich es in meiner Zeichenfolge ausprobierte (nachdem ich {Chinese} durch das passende {Han} Unicode-Skript ersetzt hatte), analysierte es die Zeichenfolge vollständig. Ich experimentierte weiter mit Unicode-Skripten und endete mit etwas, mit dem ich zufrieden war. Danke für deine Hilfe! – justinl

Verwandte Themen