Domanda

Ho iniziato con alcuni fallimenti folli utilizzando preg_replace in php e bollito giù al caso problema di avere più di una classe di caratteri utilizzando turco punteggiata "i" e undotted "i" insieme. Ecco un semplice caso di test 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";
?>

E lo stesso banco di prova di nuovo 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";

Il primo tre test funzionano bene. L'ultimo non corrisponde.

Perché questo lavoro bene come una classe di caratteri, una volta ma non la seconda volta nella stessa espressione? Come faccio a scrivere l'espressione per abbinare una parola come questo che deve corrispondere a non importa quale combinazioni di lettere è scritto con?

Modifica di base sul il problema della lingua sto cercando di programma.

Modifica 2: Aggiunta di una direttiva use utf8; fa fissare la versione perl. Dal momento che il mio problema originale era con un programma PHP e ho acceso solo per perl per vedere se si trattava di un bug in PHP, che non mi aiuta un sacco. Qualcuno sa la direttiva per rendere PHP non soffocare su questo?

È stato utile?

Soluzione

sequenze byte non farà quello che vuoi in classi char tra parentesi se l'UTF-8 è essere mis-interpretata come una sequenza di byte di 8 bit. Pensaci. Se [nñm] è misconstructed non come tre personaggi logici ma come quattro byte fisici, si potrebbe corrispondere solo un personaggio il cui punto di codice è 6E o C3 o B1 o 6D.

Per alcuni scopi, si potrebbe ottenere via con riscrittura [nñm] come (?:n|ñ|m). Dipende solo da cosa si sta facendo. roba involucro non funziona.

Inoltre, Unicode ha regole particolari di rivestimento per un errati privi di punti turco i.

Suoni come PHP non è sufficiente moderna. Sigh.

Altri suggerimenti

Si può avere bisogno di dire a Perl che il file di origine contiene caratteri utf8. Prova:

#!/usr/bin/perl

use utf8;   # **** Add this line

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

Il che non ti aiuta con PHP, ma ci può essere una direttiva simile in PHP. In caso contrario, provare a utilizzare una qualche forma di fuga-sequenza per evitare di mettere il carattere letterale nel codice sorgente. Non so niente di PHP in modo da non posso fare con questo.

Modifica
Sto leggendo che PHP non ha il supporto Unicode. Pertanto, l'ingresso unicode si passa probabilmente è trattata come la stringa di byte che l'unicode è stato codificato come.

Se si può essere certi che il vostro ingresso è in arrivo come UTF-8, allora si può abbinare per la sequenza UTF-8 per ı che è \xc4 \xb1 come in:

$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";

funziona?

Modifica di nuovo:
Posso spiegare il motivo per cui i primi tre test passano. Facciamo finta che nella codifica, ı è codificato come ABCDE. poi PHP vede il seguente:

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";

che rende evidente perché i primi tre test passano e l'ultimo fallisce. Se si utilizza un inizio / fine anchor ^...$ Penso che troverete che solo il primo test viene superato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top