2016-02-13 27 views
6

Esiste un modo in un'espressione regolare per specificare una corrispondenza per un carattere con un segno diacritico specifico? Diciamo un accento grave, per esempio. La lunga strada per farlo è quello di andare al Wikipedia page on the grave accent, copiare tutti i personaggi si vede, poi fare una classe di caratteri fuori di essi:carattere di corrispondenza regex con segno diacritico specifico

/[àầằèềḕìǹòồṑùǜừẁỳ]/i 

Questo è abbastanza noioso. Speravo in una proprietà Unicode come \p{hasGraveAccent}, ma non riesco a trovare nulla di simile. Alla ricerca di una soluzione vengono solo delle domande da parte di persone che cercano di abbinare i caratteri ignorando i segni diacritici, il che implica l'esecuzione di una normalizzazione di qualche tipo, che non è ciò che voglio.

+0

Se si tratta di un carattere di combinazione, ciò potrebbe essere possibile [generando un elenco di codepoint unicode] (http://stackoverflow.com/questions/17051732/algorithm-to-check-for-combining-characters-in-unicode). – kba

+0

Creare una classe di caratteri con lettere singole non è affidabile e non funzionerebbe.Funzionerebbe solo per le lettere precomposte che corrispondono alle stringhe NFC (modulo di normalizzazione composto). La maggior parte dei personaggi con due o più segni diacritici non ha carattere precomposto. Cioè sono costituiti da più di un punto di codice (= carattere nel parlato Unicode). Se le copi e le incolli in una classe di caratteri, il segno diacritico è ancora un singolo carattere e corrisponderà agli stessi singoli segni diacritici nella stringa di destinazione. –

risposta

0

È una domanda un po 'complicata, ma è possibile. Innanzitutto, è necessario normalizzare la stringa Unicode in uno dei 4 moduli. Le informazioni sulla normalizzazione sono here e una mappa di esempi di caratteri con le diverse normalizzazioni è here e un buon grafico per i caratteri normalizzati è here. In sostanza, la normalizzazione si limita ad assicurare che tutti i caratteri siano nello stesso formato quando si gestiscono i segni diacritici. Golang ha un grande supporto per questo, e la maggior parte di tutte le lingue dovrebbe contenere librerie per farlo.

Quindi per il mio esempio, convertire la stringa in "Normalization Form D" (NFD) e utf32, quindi tutti i caratteri Unicode sono i loro punti di codice in 4 byte.

Tutti i caratteri diacritici per l'accento grave hanno 0x0300 accanto al carattere. Quindi puoi eseguire una ricerca di espressioni regolari in modalità ascii (modalità non Unicode) per ....\x00\x00\x03\x00. Da lì dovrai estrarre la posizione della runa in cui si trova. Ciò può essere fatto con metodi diversi a seconda della codifica che stai utilizzando.

Quindi se atterri su una divisione di 4, saprai che è un carattere valido.

Oltre a questo, non ci sono gruppi di caratteri perl ufficiali per farlo.

codice Perl come esempio:

use Encode; 
use Unicode::Normalize; 

$StartUTF8='xàaâèaê'; 
$PerlEncoded=decode('utf8', $StartUTF8); 
$PerlNormalized=NFD($PerlEncoded); 
$UTF32Normalized=encode('utf32', $PerlNormalized); 

while($UTF32Normalized =~ /(....\x00\x00\x03\x00)/gs) { 
    $Pos=pos($UTF32Normalized)-8; 
    if($Pos%4==0) { 
     print("$Pos\n"); 
    } 
} 

Ma a questo punto, si potrebbe anche solo essere facendo un ciclo for nel corso dei personaggi: - \

Ho anche provato corrispondenza senza bisogno della posizione prova usando // c, ma per qualche motivo non funzionerebbe.

/^(?:....)*?(....\x00\x00\x03\x00)/gcs

+0

Non è necessario convertire in UTF32 (e, se si suppone che il risultato sia UTF-32LE, è necessario convertirlo anziché lasciarlo al caso). Inoltre, l'ipotesi che l'accento grave segue immediatamente il carattere di base potrebbe non essere corretto quando il glifo contiene più di un segno diacritico. – rici

+0

Infatti. È stata una ricerca e un test piuttosto infruttuosi – Dakusan

1

E 'possibile con alcune limitazioni.

#!perl 

use strict; 
use warnings; 

use Encode; 
use Unicode::Normalize; 
use charnames qw(); 
use utf8; # source is utf-8 

binmode(STDOUT, ":utf8"); # print in utf-8 

my $utf8_string = 'xàaâèaêòͤ'; 

my $nfd_string = NFD($utf8_string); # decompose 

my @chars_with_grave = $nfd_string =~ 
    m/ 
    (
     \p{L}   # one letter 
     \p{M}*   # 0 or more marks 
     \N{COMBINING GRAVE ACCENT} 
     \p{M}*   # 0 or more marks 
    ) 
    /xmsg; 

print join(', ',@chars_with_grave), "\n"; 

Questo stampa

$ perl utf_match_grave.pl 
à, è, òͤ 

NOTA: I caratteri nell'area di modifica siano correttamente visualizzate come combinato, ma StackOverflow rende loro torto separati.

Ha bisogno di una lettera come carattere di base. Cambia l'espressione regolare per altri caratteri di base. Mark \p{M} forse non è esattamente quello che vuoi, dovrebbe essere migliorato.