Làm cách nào để xuất UTF-8 từ Perl?


110

Tôi đang cố gắng viết một tập lệnh Perl bằng pragma "utf8" và tôi nhận được kết quả không mong đợi. Tôi đang sử dụng Mac OS X 10.5 (Leopard) và tôi đang chỉnh sửa bằng TextMate. Tất cả các cài đặt của tôi cho cả trình chỉnh sửa và hệ điều hành của tôi đều được đặt mặc định để viết tệp ở định dạng utf-8.

Tuy nhiên, khi tôi nhập phần sau vào một tệp văn bản, lưu nó dưới dạng ".pl" và thực thi nó, tôi nhận được "hình thoi có dấu chấm hỏi" thân thiện thay cho các ký tự không phải ASCII.

#!/usr/bin/env perl -w

use strict;
use utf8;

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

Bất kỳ ý tưởng những gì tôi đang làm sai? Tôi mong đợi nhận được 'Çirçös' trong đầu ra, nhưng thay vào đó tôi nhận được ' ir s'.


1
Có lẽ nó không phải là chương trình .. tôi nghĩ rằng nó shell của bạn oder soạn thảo của bạn mà không có đầu ra
n00ki3

Tất cả các câu trả lời trả lời chính xác câu hỏi của bạn về cách đặt nó rõ ràng thành UTF8. Tôi nghĩ rằng bạn nên điều chỉnh cài đặt ngôn ngữ của thiết bị đầu cuối của bạn như được hiển thị trong stackoverflow.com/a/14405949/498634 . Đầu cuối có thể không được đặt thành UTF8 và sau đó dữ liệu được ghi vào STDOUT trong UTF8 sẽ được mã hóa không chính xác !
Daniel Böhmer,

Câu trả lời tuyệt vời về cách làm việc với utf8:
Eugen Konkov

Câu trả lời:


160

use utf8;không kích hoạt đầu ra Unicode - nó cho phép bạn nhập Unicode trong chương trình của mình. Thêm điều này vào chương trình, trước print()tuyên bố của bạn :

binmode(STDOUT, ":utf8");

Xem nếu điều đó có ích. Điều đó sẽ tạo STDOUTra đầu ra trong UTF-8 thay vì ASCII thông thường.


Tôi không biết về điều này (tôi chỉ đưa UTF8 vào cơ sở dữ liệu, chưa bao giờ in nó). +1.
Paul Tomblin

1
Không có gì. Xem thêm một câu trả lời đúng khác: stackoverflow.com/questions/627661/writing-perl-code-in-utf8/… và nhớ TMTOWTDI. Và @ Paul - Nếu bạn đang viết UTF-8 vào một tập tin, bạn nên có lẽ sử dụng binmode () trên filehandle đó và làm cho nó "đúng" UTF-8, nhưng nếu nó hoạt động ..
Chris Lutz

1
các cách khác: pragma mở ( search.cpan.org/perldoc/open ), công tắc -C ( perldoc.perl.org/perlrun.html#-C )
ysth

1
FWIW ở đây là lý do: các chuỗi chỉ chứa các ký tự latin1 (ISO-8859-1), mặc dù được lưu trữ ít nhiều trong utf8, sẽ được xuất dưới dạng latin1 theo mặc định. Bằng cách này, các tập lệnh từ thời kỳ tiền unicode vẫn hoạt động như cũ, ngay cả với perl nhận dạng unicode.
mirod

3
Pragma utf8 không cho phép bạn viết nguồn của mình trong UNICODE, nó buộc phải hiểu nguồn của bạn ở dạng mã hóa UTF-8 (hoặc UTF-EBCDIC) của UNICODE, một điểm khác biệt quan trọng.
Chà. Owens

83

Bạn có thể sử dụng pragma mở .

Ví dụ. bên dưới đặt STDOUT, STDIN & STDERR để sử dụng UTF-8 ....

use open qw/:std :utf8/;

1
BTW ... Tôi đã cho bạn +1. Tôi nghĩ rằng binmode (STDOUT, ': utf8') có lẽ đúng hơn trong tình huống này. "use open" có những cách sử dụng tốt khác nhưng tôi dường như không thể tìm thấy cách bạn có thể đặt nó thành chỉ mã hóa STDOUT mà thôi?
draegtun

66

TMTOWTDI , đã chọn phương pháp phù hợp nhất với cách bạn làm việc. Tôi sử dụng phương pháp môi trường để tôi không phải suy nghĩ về nó.

Trong môi trường :

export PERL_UNICODE=SDL

trên dòng lệnh :

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

hoặc với binmode :

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

hoặc với 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";

hoặc với pragma mở :

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

1
+1 để có câu trả lời toàn diện; lưu ý rằng SDLđược ngụ ý cả với -CPERL_UNICODE. Các use open ':locale'pragma cũng đáng nhắc đến, bởi vì nó là tương đương trong kịch bản của -Cexport PER_UNICODE=. Bất kỳ điều nào trong số 3 điều này sẽ cung cấp cho bạn hỗ trợ UTF8 cho tất cả các luồng đầu vào và đầu ra (cho dù là tệp hoặc stdin / stdout / stderr), giả sử ngôn ngữ môi trường của bạn dựa trên UTF8. Cuối cùng, để coi mã nguồn là UTF8, hãy sử dụng use utf8;pragma.
mklement0

perl -Mutf8 -CSDL -e '...'cho phép tiêu thụ / xuất UTF-8 cũng như sử dụng các ký tự UTF-8 bên trong -eví dụ như cho thư mục trường hợp của một người đàn ông nghèo:perl -Mutf8 -CASDL -pe 'y/āáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜĀÁǍÀĒÉĚÈĪÍǏÌŌÓǑÒŪÚǓÙǕǗǙǛ/aaaaeeeeiiiioooouuuuüüüüAAAAEEEEIIIIOOOOUUUUÜÜÜÜ/'
vladr


0

Cảm ơn, cuối cùng đã có một giải pháp để không đặt utf8 :: encode lên toàn bộ mã. Để tổng hợp và hoàn thành cho các trường hợp khác, như ghi và đọc tệp trong utf8 và cũng hoạt động với LoadFile của tệp YAML trong 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}." ";

nơi cache.yaml là:

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

-3

làm trong shell của bạn: $ env | grep LANG

Điều này có thể sẽ cho thấy rằng trình bao của bạn không sử dụng ngôn ngữ utf-8.


Trên thực tế, nó đã được đặt thành utf-8. Vấn đề là tôi đang xuất ra STDOUT mà không đặt binmode thành utf-8;

2
Đây sẽ là một mối quan tâm trực giao. Bạn cần tập lệnh Perl của mình để xuất dữ liệu chính xác trước khi bạn có thể lo lắng về cách trình giả lập đầu cuối của bạn diễn giải nó.
jrockway
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.