Bagaimana cara mengeluarkan UTF-8 dari Perl?


110

Saya mencoba menulis skrip Perl menggunakan pragma "utf8", dan saya mendapatkan hasil yang tidak diharapkan. Saya menggunakan Mac OS X 10.5 (Leopard), dan saya mengedit dengan TextMate. Semua pengaturan saya untuk editor dan sistem operasi saya secara default menulis file dalam format utf-8.

Namun, ketika saya memasukkan yang berikut ini ke dalam file teks, menyimpannya sebagai ".pl", dan menjalankannya, saya mendapatkan "berlian dengan tanda tanya" sebagai pengganti karakter non-ASCII.

#!/usr/bin/env perl -w

use strict;
use utf8;

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

Tahu apa yang saya lakukan salah? Saya berharap mendapatkan 'Çirçös' di output, tetapi saya mendapatkan ' ir s' sebagai gantinya.


1
Mungkin ini bukan programnya .. saya pikir shell Anda atau editor Anda yang melakukan output
— n00ki3

Semua jawaban menjawab dengan benar pertanyaan Anda bagaimana mengaturnya secara eksplisit ke UTF8. Saya pikir Anda harus menyesuaikan dengan pengaturan lokal terminal Anda seperti yang ditunjukkan di stackoverflow.com/a/14405949/498634 . Terminal mungkin tidak disetel ke UTF8 dan kemudian data yang ditulis ke STDOUT dalam UTF8 akan dienkode dengan tidak benar !
— Daniel Böhmer

Jawaban yang bagus bagaimana bekerja dengan utf8:
— Eugen Konkov

Jawaban:


160

use utf8;tidak mengaktifkan keluaran Unicode - ini memungkinkan Anda untuk mengetik Unicode dalam program Anda. Tambahkan ini ke program, sebelum print()pernyataan Anda :

binmode(STDOUT, ":utf8");

Lihat apakah itu membantu. Itu harus membuat STDOUTkeluaran dalam UTF-8, bukan ASCII biasa.


Saya tidak tahu tentang ini (saya hanya meletakkan UTF8 dalam database, tidak pernah mencetaknya). +1.
— Paul Tomblin

1
Sama-sama. Lihat juga jawaban lain yang benar: stackoverflow.com/questions/627661/writing-perl-code-in-utf8/… dan ingat, TMTOWTDI. Dan @Paul - jika Anda menulis UTF-8 ke sebuah file, Anda mungkin harus menggunakan binmode () pada filehandle itu dan menjadikannya UTF-8 yang "layak", tetapi jika berhasil ..
— Chris Lutz

1
cara lain: pragma terbuka ( search.cpan.org/perldoc/open ), tombol -C ( perldoc.perl.org/perlrun.html#-C )
— ysth

1
Alasannya adalah FWIW: string yang hanya berisi karakter latin1 (ISO-8859-1), meskipun disimpan lebih atau kurang di utf8, akan menjadi keluaran latin1 secara default. Dengan cara ini skrip dari era pra-unicode masih berfungsi sama, bahkan dengan perl yang peka unicode.
— mirod

3
Pragma utf8 tidak mengizinkan Anda menulis sumber dalam UNICODE, ini memaksa pemahaman tentang sumber Anda dalam pengkodean UTF-8 (atau UTF-EBCDIC) UNICODE, perbedaan penting.
— Chas. Owens

83

Anda bisa menggunakan pragma terbuka .

Misalnya. di bawah ini menetapkan STDOUT, STDIN & STDERR untuk menggunakan UTF-8 ....

use open qw/:std :utf8/;

1
BTW ... Aku memberimu +1. Saya pikir binmode (STDOUT, ': utf8') mungkin lebih tepat dalam situasi ini. "gunakan terbuka" memiliki kegunaan lain yang baik tetapi saya tidak dapat menemukan bagaimana Anda dapat mengaturnya untuk hanya menyandikan STDOUT saja?
— draegtun

66

TMTOWTDI , pilih metode yang paling sesuai dengan cara Anda bekerja. Saya menggunakan metode lingkungan jadi saya tidak perlu memikirkannya.

Di lingkungan :

export PERL_UNICODE=SDL

di baris perintah :

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

atau dengan binmode :

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

atau dengan PerlIO :

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

atau dengan pragma terbuka :

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

1
1 untuk jawaban komprehensif; catatan yang SDLtersirat baik dengan -Cdan PERL_UNICODE. The use open ':locale'pragma juga layak disebutkan, karena itu adalah di-script setara -Cdan export PER_UNICODE=. Salah satu dari 3 ini akan memberi Anda dukungan UTF8 untuk semua aliran input dan output (baik file atau stdin / stdout / stderr), dengan asumsi lokal lingkungan Anda berbasis UTF8. Terakhir, untuk juga memperlakukan kode sumber sebagai UTF8, gunakan use utf8;pragma.
— mklement0

perl -Mutf8 -CSDL -e '...'memungkinkan untuk mengkonsumsi / mengeluarkan UTF-8 serta menggunakan literal UTF-8 di dalam -emisalnya untuk folder kasus orang miskin:perl -Mutf8 -CASDL -pe 'y/āáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜĀÁǍÀĒÉĚÈĪÍǏÌŌÓǑÒŪÚǓÙǕǗǙǛ/aaaaeeeeiiiioooouuuuüüüüAAAAEEEEIIIIOOOOUUUUÜÜÜÜ/'
— vladr


0

Terima kasih, akhirnya mendapat solusi untuk tidak meletakkan utf8 :: encode di seluruh kode. Untuk mensintesis dan menyelesaikan kasus lain, seperti menulis dan membaca file di utf8 dan juga bekerja dengan LoadFile dari file YAML di utf8

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

di mana cache.yaml adalah:

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

-3

lakukan di shell Anda: $ env | grep LANG

Ini mungkin akan menunjukkan bahwa shell Anda tidak menggunakan lokal utf-8.


Sebenarnya, ini disetel ke utf-8. Masalahnya adalah saya mengeluarkan output ke STDOUT tanpa menyetel binmode ke utf-8;

2
Ini akan menjadi perhatian ortogonal. Anda memerlukan skrip Perl untuk mengeluarkan data yang benar sebelum Anda khawatir tentang bagaimana emulator terminal Anda menafsirkannya.
— jrockway
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.