Frage

begann ich mit einigen verrückten Ausfällen Verwendung von preg_replace in PHP und kochte es zum Problemfall nach unten mehr mit als ein Zeichenklasse mit türkischer gepunkteten „i“ und zusammen „I“ ungepunkteten. Hier ist ein einfacher Testfall in PHP:

<?php
    echo 'match single normal i: ';
    $str = 'mi';
    echo (preg_match('!m[ıi]!', $str)) ? "ok\n" : "fail\n";

    echo 'match single undotted ı: ';
    $str = 'mı';
    echo (preg_match('!m[ıi]!', $str)) ? "ok\n" : "fail\n";

    echo 'match double normal i: ';
    $str = 'misir';
    echo (preg_match('!m[ıi]s[ıi]r!', $str)) ? "ok\n" : "fail\n";

    echo 'match double undotted ı: ';
    $str = 'mısır';
    echo (preg_match('!m[ıi]s[ıi]r!', $str)) ? "ok\n" : "fail\n";
?>

Und der gleiche Testfall wieder in Perl:

#!/usr/bin/perl

$str = 'mi';
$str =~ m/m[ıi]/ && print "match single normal i\n";

$str = 'mı';
$str =~ m/m[ıi]/ && print "match single undotted ı\n";

$str = 'misir';
$str =~ m/m[ıi]s[ıi]r/ && print "match double normal i\n";

$str = 'mısır';
$str =~ m/m[ıi]s[ıi]r/ && print "match double undotted ı\n";

Die ersten drei Tests funktionieren. Der letzte stimmt nicht überein.

Warum funktioniert das fein wie ein Zeichenklasse einmal, aber nicht das zweite Mal in dem gleichen Ausdruck? Wie schreibe ich einen Ausdruck für ein Wort so entsprechen, dass Bedürfnisse, egal entsprechen, was Kombinationen von Buchstaben, mit dem es geschrieben?

Edit: Hintergrund auf das Sprachproblem ich versuche Programm für.

Edit 2: eine use utf8; Richtlinie Hinzufügen nicht beheben die Perl-Version. Da mein ursprüngliches Problem mit einem PHP-Programm war und wechselte ich nur Perl zu sehen, ob es ein Fehler in PHP war, das hilft mir nicht viel. kennt jemand die Richtlinie PHP nicht auf diese ersticken zu machen?

War es hilfreich?

Lösung

Multibyte-Sequenzen werden nicht tun, was Sie in klammert char Klassen wollen, wenn die UTF-8 falsch interpretiert als eine Folge von 8-Bit-Bytes zu sein. Denk darüber nach. Wenn [nñm] nicht als drei logische Zeichen misconstructed, sondern als vier physische Bytes, würden Sie nur ein Zeichen entsprechen, dessen Codepunkt ist 6E oder C3 oder B1 oder 6D.

Für manche Zwecke können Sie auch mit Umschreiben [nñm] als (?:n|ñ|m) wegzukommen. Es hängt davon ab, was Sie tun. Gehäuse Material wird nicht funktionieren.

Auch hat Unicode spezielle Gehäuse Regeln für einen türkischen i ohne Punkt.

Sounds wie PHP ist einfach nicht modern genug. Seufz.

Andere Tipps

Möglicherweise müssen Sie Perl sagen, dass die Quelldatei UTF-8-Zeichen enthält. Versuchen Sie:

#!/usr/bin/perl

use utf8;   # **** Add this line

$str = 'mısır';
$str =~ m/m[ıi]s[ıi]r/ && print "match double undotted ı\n";

Was dir nicht mit PHP hilft, aber es kann eine ähnliche Richtlinie in PHP sein. Ansonsten versuchen, irgendeine Form von Escape-Sequenz unter Verwendung zu vermeiden, in Ihrem Source-Code, um die wörtlichen Zeichen setzen. Ich weiß nichts über PHP so kann ich nicht helfen mit, dass.

Bearbeiten
Ich lese, dass PHP keine Unicode-Unterstützung hat. Daher wahrscheinlich die Unicode-Eingabe Sie es passieren, wie die Kette von Bytes behandelt wird, dass der Unicode als codiert wurde.

Wenn Sie sicher sein, dass Ihre Eingabe kommt in als utf-8, dann können Sie für die utf-8-Sequenz für ı entsprechen, die \xc4 \xb1 ist etwa so:

$str = 'mısır';  # Make sure this source-file is encoded as utf-8 or this match will fail
echo (preg_match('!m(i|\xc4\xb1)s(i|\xc4\xb1)r!', $str)) ? "ok\n" : "fail\n";

geht das?

Bearbeiten wieder:
Ich kann erklären, warum Ihre ersten drei Tests bestehen. Nehmen wir an, dass in der Codierung, ı als ABCDE codiert wird. dann PHP sieht Folgendes:

echo 'match single normal i: ';
$str = 'mi';
echo (preg_match('!m[ABCDEi]!', $str)) ? "ok\n" : "fail\n";

echo 'match single undotted ABCDE: ';
$str = 'mABCDE';
echo (preg_match('!m[ABCDEi]!', $str)) ? "ok\n" : "fail\n";

echo 'match double normal i: ';
$str = 'misir';
echo (preg_match('!m[ABCDEi]s[ABCDEi]r!', $str)) ? "ok\n" : "fail\n";

echo 'match double undotted ABCDE: ';
$str = 'mABCDEsABCDEr';
echo (preg_match('!m[ABCDEi]s[ABCDEi]r!', $str)) ? "ok\n" : "fail\n";

, die es offensichtlich macht, warum die ersten drei Tests bestehen und die letzte ausfällt. Wenn Sie einen Start / Ende Anker ^...$ verwenden glaube ich Sie, dass nur der erste Test finden passiert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top