2011-11-25 12 views
6

nie mogę pozbyć się szczególnym charakterze ¤ i w ciąg:Regexp nie działa dla poszczególnych znaków specjalnych w Perl

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

na drugiej linii staram się usunąć dowolne znaki nie alfabetyczne ze stringa $word. Spodziewam się, aby słowo cyrk drukowany ale zamiast uzyskać:

ci�rc�us 

OAA i OAA w wyrażeniu są po prostu normalne znaki alfabetu szwedzkiego że muszę wliczony w cenę.

+0

Z którą wersją perla pracujesz? Wsparcie dla Unicode było stopniowo dodawane i ulepszane. Spróbuj pracować z co najmniej 5,12 i spójrz na odpowiedź choroby. 'perl -v', aby wydrukować wersję. [Podręcznik perl unicode] (http://perldoc.perl.org/perlunicode.html) – cfi

+0

Wersja jest w wersji 5.12.4 – Pithikos

+0

Dlaczego doświadczeni programiści ciągle zmieniają pytania? Teraz żaden użytkownik mojego (niskiego) doświadczenia nigdy nie znajdzie odpowiedzi na swoje pytanie. – Pithikos

Odpowiedz

11

Jeśli znaki są w kodzie źródłowym, należy się upewnić, że: use utf8. Jeśli są czytane z pliku, binmode $FILEHANDLE, ':utf8'.

Należy przeczytać .

+0

Myślę, że kodowanie jest poprawne, ponieważ mogę "printf" cɞi¤r $ c❤u¨söäå ";' bez problemu. Problem pojawia się, gdy uruchomię wyrażenie regularne. Usunięcie ** öäå ** z wyrażenia regularnego rozwiązuje problem, ale nie mogę użyć tych znaków w łańcuchu:/ – Pithikos

+1

Możesz wydrukować ciąg znaków nawet bez 'use utf8', ale w takim przypadku Perl drukuje _bytes_ nie _characters_. Właśnie dlatego nie rozpoznaje znaków w regex. Czy czytałeś "perlunicode"? – choroba

-7

Jak pointed out by choroba, dodając, to na początku skryptu perla rozwiązuje go:

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

gdzie use utf8 pozwala używać znaków specjalnych poprawnie w wyrażeniu regularnym i binmode(STDOUT, ":utf8") pozwala Ci wyjście znaki specjalne poprawnie na muszla.

+3

Tak właśnie zaproponowała już choroba. Dlaczego dostarczyłeś kopię jego odpowiedzi? Zamiast tego nagradzaj chorobę "odpowiedzią" (a także prowokuj go) (a następnie usuń własną odpowiedź) – cfi

+0

Ponieważ moja odpowiedź jest bardziej pragmatyczna. Nie próbuję z nim konkurować. Próbuję opracować dla przyszłych użytkowników, którzy mają stos na tym samym problemie. Im więcej odpowiedzi, tym lepiej w mojej opinii. – Pithikos

+2

@Pithikos, możesz dodać go jako niewielki komentarz do swojej odpowiedzi, zwłaszcza jeśli pokazał ci drogę. – Qtax

3

Krótka odpowiedź: dodaj użytek utf8; aby upewnić się, że Twój ciąg literowy w kodzie źródłowym jest interpretowany jako utf8, który zawiera treść ciągu testowego i treść wyrażenia regularnego.

Długa odpowiedź:

#!/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"); 

Wykonywanie go bez 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 

Wykonanie go z 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 

wyjaśnienie:

The znaki spoza ASCII ty Ponowne wpisanie kodu źródłowego jest reprezentowane przez jeden lub więcej bajtów. Ponieważ twoje wejście jest zakodowane utf8. W czystym terminalu ASCII lub Latin-1 znaki byłyby jednym bajtem.

Gdy nie używa się modułu utf8, perl uważa, że ​​każdy wprowadzany bajt jest oddzielną postacią, jak widać podczas dzielenia i drukowania każdego indywidualnego znaku. Podczas korzystania z modułu utf8 traktuje kombinację kilku bajtów jako jeden znak poprawnie zgodnie z zasadami kodowania utf8.

Jak widać na podstawie liczby monet, niektóre z bajtów, które składają się na szwedzkie znaki, składają się z niektórych bajtów, z których składa się część znaków w łańcuchu testowym, i są one przechowywane. Mianowicie: ö, który w utf8 składa się z 195: Ã 164: ¤ - 164 kończy się jako jedna z dozwolonych przez ciebie postaci i przechodzi przez nią.

Rozwiązaniem jest poinformowanie perla, że ​​twoje struny mają być uważane za utf-8.

Dostępne są wywołania encode_utf8 w celu uniknięcia ostrzeżeń o szerokich znakach drukowanych na terminalu. Jak zwykle, musisz dekodować wejście i kodować wyjście zgodnie z kodowaniem znaków, które wejście lub wyjście ma obsługiwać/obsługiwać.

Mam nadzieję, że dzięki temu stało się jaśniejsze.

+0

Blah, przepraszam, że mam nałożoną na siebie odpowiedź. Jeśli chcesz, możesz je usunąć lub zignorować ;- / – nicomen

Powiązane problemy