UTF-8'i Perl'den nasıl çıkarabilirim?


110

"Utf8" pragmasını kullanarak bir Perl betiği yazmaya çalışıyorum ve beklenmedik sonuçlar alıyorum. Mac OS X 10.5 (Leopard) kullanıyorum ve TextMate ile düzenleme yapıyorum. Hem editörüm hem de işletim sistemim için tüm ayarlarım varsayılan olarak dosyaları utf-8 biçiminde yazacak şekilde ayarlandı.

Ancak, aşağıdakini bir metin dosyasına girip, onu bir ".pl" olarak kaydettiğimde ve çalıştırdığımda, ASCII olmayan karakterlerin yerine dostça "soru işaretli elmas" alıyorum.

#!/usr/bin/env perl -w

use strict;
use utf8;

my $str = 'Çirçös';
print( "$str\n" );

Neyi yanlış yaptığım hakkında bir fikrin var mı? Çıktıda 'Çirçös' olmasını bekliyorum ama onun yerine 'ir s' alıyorum.


1
Belki bu program değildir .. bence onun kabuğunuz çıktıyı yapan editörünüz
n00ki3

Tüm yanıtlar, sorunuzu nasıl açıkça UTF8 olarak ayarlayacağınızı doğru bir şekilde yanıtlar. Stackoverflow.com/a/14405949/498634 adresinde gösterildiği gibi terminalinizin yerel ayarlarına ayarlamanız gerektiğini düşünüyorum . Terminal UTF8'e ayarlanmamış olabilir ve bu durumda STDOUT'a UTF8'de yazılan veriler yanlış kodlanacaktır !
Daniel Böhmer

Nasıl çalışılacağına harika bir cevaputf8 :
Eugen Konkov

Yanıtlar:


160

use utf8;Unicode çıktısını etkinleştirmez - programınızda Unicode yazmanıza olanak tanır. İfadenizden önce bunu programa ekleyin print():

binmode(STDOUT, ":utf8");

Bunun yardımcı olup olmadığına bak. Bu STDOUT, sıradan ASCII yerine UTF-8'de çıktı almalıdır .


Bunu bilmiyordum (sadece UTF8'i bir veritabanına koyuyordum, asla yazdırmadım). +1.
Paul Tomblin

1
Rica ederim. Ayrıca başka bir doğru yanıta bakın: stackoverflow.com/questions/627661/writing-perl-code-in-utf8/… ve unutmayın, TMTOWTDI. Ve @Paul - bir dosyaya UTF-8 yazıyorsanız, muhtemelen o dosya tanıtıcısı üzerinde binmode () kullanmalı ve onu "uygun" UTF-8 yapmalısınız, ancak işe yararsa ..
Chris Lutz

1
Diğer yollar: Açık Pragma ( search.cpan.org/perldoc/open ), -C anahtar ( perldoc.perl.org/perlrun.html#-C )
ysth

1
FWIW'nin nedeni şudur: utf8'de az ya da çok saklanmasına rağmen yalnızca latin1 (ISO-8859-1) karakterleri içeren dizeler varsayılan olarak latin1 olarak çıktılanacaktır. Bu şekilde, unicode öncesi dönemdeki komut dosyaları, unicode duyarlı bir perl ile bile aynı şekilde çalışır.
mirod

3
Utf8 pragma, kaynağınızı UNICODE olarak yazmanıza izin vermez, kaynağınızı UNICODE'un UTF-8 (veya UTF-EBCDIC) kodlamasında anlamaya zorlar, bu önemli bir ayrımdır.
Chas. Owens

83

Açık pragmayı kullanabilirsiniz .

Örneğin. aşağıda STDOUT, STDIN ve STDERR komutlarını UTF-8 kullanacak şekilde ayarlar ....

use open qw/:std :utf8/;

1
BTW ... ben + 1 verdim. Bence binmode (STDOUT, ': utf8') bu durumda muhtemelen daha doğru. "açık kullan" ın başka iyi kullanımları da var ama onu yalnızca STDOUT'u kodlamak için nasıl ayarlayabileceğimi bulamıyorum?
draegtun

66

TMTOWTDI , çalışma şeklinize en uygun yöntemi seçin. Çevre yöntemini kullanıyorum, böylece düşünmek zorunda kalmıyorum.

In çevre :

export PERL_UNICODE=SDL

üzerinde komut satırından :

perl -CSDL -le 'print "\x{1815}"';

veya binmode ile :

binmode(STDOUT, ":utf8");          #treat as if it is UTF-8
binmode(STDIN, ":encoding(utf8)"); #actually check if it is UTF-8

veya PerlIO ile :

open my $fh, ">:utf8", $filename
    or die "could not open $filename: $!\n";

open my $fh, "<:encoding(utf-8)", $filename
    or die "could not open $filename: $!\n";

veya açık pragma ile :

use open ":encoding(utf8)";
use open IN => ":encoding(utf8)", OUT => ":utf8";

1
Kapsamlı bir cevap için +1; SDLhem -Cve hem de ima edildiğini unutmayın PERL_UNICODE. use open ':locale'Bunun içinde komut eşdeğerdir çünkü Pragma da bahsetmemiz olduğunu -Cve export PER_UNICODE=. Bu 3'ten herhangi biri, ortamınızın yerel ayarının UTF8 tabanlı olduğunu varsayarak, tüm girdi ve çıktı akışları için (ister dosyalar ister stdin / stdout / stderr olsun) size UTF8 desteği verecektir. Son olarak, kaynak kodunu UTF8 olarak değerlendirmek için pragmayı kullanın use utf8;.
mklement0

perl -Mutf8 -CSDL -e '...'/ çıkış UTF-8 tüketmek sağlar hem içeride gibi kullanım UTF-8 değişmezleri -ebir fakirin dava klasörü için örneğin:perl -Mutf8 -CASDL -pe 'y/āáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜĀÁǍÀĒÉĚÈĪÍǏÌŌÓǑÒŪÚǓÙǕǗǙǛ/aaaaeeeeiiiioooouuuuüüüüAAAAEEEEIIIIOOOOUUUUÜÜÜÜ/'
vladr


0

Teşekkürler, sonunda utf8 :: kodlamasını kodun her yerine koymamak için bir çözüm buldum. Utf8'deki dosyaları yazmak ve okumak gibi diğer durumlar için sentezlemek ve tamamlamak ve ayrıca utf8'deki YAML dosyasının LoadFile ile çalışır

use utf8;
use open ':encoding(utf8)';
binmode(STDOUT, ":utf8");

open(FH, ">test.txt"); 
print FH "something éá";

use YAML qw(LoadFile Dump);
my $PUBS = LoadFile("cache.yaml");
my $f = "2917";
my $ref = $PUBS->{$f};
print "$f \"".$ref->{name}."\" ". $ref->{primary_uri}." ";

cache.yaml burada:

---
2917:
  id: 2917
  name: Semanário
  primary_uri: 2917.xml

-3

kabuğunuzda yapın: $ env | grep LANG

Bu muhtemelen kabuğunuzun bir utf-8 yerel ayarı kullanmadığını gösterecektir.


Aslında utf-8 olarak ayarlandı. Sorun, binmode'u utf-8'e ayarlamadan STDOUT'a çıktı almamdı;

2
Bu ortogonal bir endişe olacaktır. Terminal öykünücünüzün bunları nasıl yorumlayacağı konusunda endişelenmeden önce doğru verileri çıkarmak için Perl betiğinize ihtiyacınız vardır.
jrockway
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.