2011-11-25 14 views
6

non riesco a sbarazzarsi del carattere speciale ¤ e in una stringa:Regexp non funziona per i caratteri speciali specifici in Perl

$word = 'cɞi¤r$c❤u¨s'; 
$word =~ s/[^a-zöäåA-ZÖÄÅ]//g; 
printf "$word\n"; 

Sulla seconda riga provo a rimuovere qualsiasi non alfabetico caratteri dalla stringa $word. Mi aspetto di ottenere la parola circo stampata ma invece ottengo:

ci�rc�us 

Il OAA e OAA nell'espressione sono personaggi appena normali dell'alfabeto svedese che ho bisogno incluso.

+0

Con quale versione stai lavorando? Il supporto Unicode è stato gradualmente aggiunto e perfezionato. Prova a lavorare con almeno 5.12, e guarda la risposta di Choroba. 'perl -v' per stampare la versione. [Manuale per per unicode] (http://perldoc.perl.org/perlunicode.html) – cfi

+0

La versione è v5.12.4 – Pithikos

+0

Perché i programmatori esperti continuano a cambiare le domande? Ora nessun utente della mia (scarsa) esperienza troverà mai la risposta alla sua domanda. – Pithikos

risposta

11

Se i caratteri sono nel codice sorgente, assicurarsi di use utf8. Se vengono letti da un file, binmode $FILEHANDLE, ':utf8'.

Assicurarsi di leggere perldoc perlunicode.

+0

Penso che la codifica sia corretta in quanto posso 'printf 'cɞi¤r $ c❤u¨söäå';' senza problemi. Il problema si presenta quando eseguo l'espressione regolare. La rimozione di ** öåå ** da regexp risolve il problema, ma non posso usare quei caratteri nella mia stringa:/ – Pithikos

+1

Puoi stampare la stringa anche senza 'usare utf8', ma in tal caso, Perl sta stampando _bytes_ , non _caratteri_. Questo è anche il motivo per cui non riconosce i caratteri nella regex. Hai letto 'perlunicode'? – choroba

-7

Come pointed out by choroba, aggiungendo questo all'inizio dello script perl lo risolve:

use utf8; 
binmode(STDOUT, ":utf8"); 

dove use utf8 consente di utilizzare correttamente i caratteri speciali nelle espressioni regolari e binmode(STDOUT, ":utf8") consente di emettere i caratteri speciali in modo corretto sulla conchiglia.

+3

Questo è ciò che già suggeriva il choroba. Perché fornisci una copia della sua risposta? Invece premi ricompensa a Choroba con la "risposta" (e anche su di lui) (e poi cancella la tua risposta) – cfi

+0

Perché la mia risposta è più pragmatica. Non cerco di competere con lui. Cerco di elaborare per gli utenti futuri che ottengono stack sullo stesso problema. Più risposte, meglio è, secondo me. – Pithikos

+2

@Pithikos, potresti aggiungerlo come commento secondario alla sua risposta, specialmente se ti mostrasse la strada. – Qtax

3

Risposta breve: aggiungere utilizzare utf8; per assicurarti che la tua stringa letterale nel codice sorgente sia interpretata come utf8, che includa il contenuto della stringa di test e il contenuto della regexp.

Risposta lunga:

#!/usr/bin/env perl 

use warnings; 
use Encode; 

my $word = 'cɞi¤r$c❤u¨s'; 

foreach my $char (split //, $word) { 
    print ord($char) . Encode::encode_utf8(":$char "); 
} 

my $allowed_chars = 'a-zöäåA-ZÖÄÅ'; 

print "\n"; 

foreach my $char (split //, $allowed_chars) { 
    print ord($char) . Encode::encode_utf8(":$char "); 
} 

print "\n"; 

$word =~ s/[^$allowed_chars]//g; 

printf Encode::encode_utf8("$word\n"); 

esecuzione senza utf8:

$ perl utf8_regexp.pl 
99:c 201:É 158: 105:i 194:Â 164:¤ 114:r 36:$ 99:c 226:â 157: 164:¤ 117:u 194:Â 168:¨ 115:s 
97:a 45:- 122:z 195:Ã 182:¶ 195:Ã 164:¤ 195:Ã 165:¥ 65:A 45:- 90:Z 195:Ã 150: 195:Ã 132: 195:Ã 133: 
ci¤rc¤us 

esecuzione con utf8:

$ perl -Mutf8 utf8_regexp.pl 
99:c 606:ɞ 105:i 164:¤ 114:r 36:$ 99:c 10084:❤ 117:u 168:¨ 115:s 
97:a 45:- 122:z 246:ö 228:ä 229:å 65:A 45:- 90:Z 214:Ö 196:Ä 197:Å 
circus 

Spiegazione:

I caratteri non ASCII tu a La reinserzione nel codice sorgente è rappresentata da uno più byte. Dal momento che il tuo input è codificato utf8. In un puro ASCII o terminale latino-1 i caratteri sarebbero stati un byte.

Quando non si utilizza il modulo utf8, perl pensa che ogni singolo byte che si sta inserendo è un carattere separato, come si può vedere quando si esegue la divisione e la stampa di ogni singolo carattere. Quando si utilizza il modulo utf8, tratta la combinazione di più byte come un carattere correttamente secondo le regole della codifica utf8.

Come si può vedere da coinscidence, alcuni dei byte che i caratteri svedesi sono costituiti da corrispondere con alcuni dei byte che alcuni dei caratteri nella stringa di prova sono costituiti, e sono mantenuti. Vale a dire: il ö che in utf8 consiste di 195: Ã 164: ¤ - Il 164 finisce come uno dei personaggi che permetti e passa attraverso.

La soluzione è di dire perl che le tue stringhe dovrebbero essere considerate come utf-8.

Le chiamate encode_utf8 sono attive per evitare avvisi relativi ai caratteri ampi stampati sul terminale. Come sempre, è necessario decodificare l'input e codificare l'output in base alla codifica dei caratteri che l'input o l'output deve gestire/utilizzare.

Spero che ciò sia reso più chiaro.

+0

Blah, mi dispiace per avere una risposta sovrapposta. Sentiti libero di cancellare o meno questo, se vuoi; – nicomen

Problemi correlati