2009-03-09 24 views
92

Tôi đang cố gắng viết kịch bản Perl bằng cách sử dụng "pragma" utf8 và tôi nhận được kết quả không mong muốn. 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 soạn thảo và hệ điều hành của tôi đều được mặc định để ghi tệp theo định dạng utf-8.Làm thế nào tôi có thể xuất UTF-8 từ Perl?

Tuy nhiên, khi tôi nhập nội dung sau vào tệp văn bản, hãy lưu nó dưới dạng ".pl" và thực thi nó, tôi nhận "kim cương có dấu hỏi" thân thiện thay cho 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 nào tôi đang làm sai? Tôi mong đợi để có được 'Çirçös' trong đầu ra, nhưng tôi nhận được ' ir s' thay thế.

+1

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

Trả lời

141

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

Xem điều đó có hữu ích không. Điều đó sẽ làm cho đầu ra STDOUT trong UTF-8 thay vì ASCII thông thường.

+0

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

+0

Điều đó có hiệu quả, Chris. Cảm ơn bạn! –

+1

Bạn được chào đón. Xem thêm một câu trả lời đúng: http://stackoverflow.com/questions/627661/writing-perl-code-in-utf8/627975#627975 và nhớ, TMTOWTDI. Và @Paul - nếu bạn đang viết UTF-8 vào một tệp, có lẽ bạn nên sử dụng binmode() trên tệp đó và làm cho nó "đúng" UTF-8, nhưng nếu nó hoạt động .. –

-2

Chuyển hướng đầu ra sang tệp văn bản và thử điều đó trong trình chỉnh sửa. Nếu nó hiển thị tốt thì thiết bị đầu cuối của bạn có lỗi.

+0

Không, thiết bị đầu cuối Leopard có $ LANG được đặt thành "en_US.UTF-8" theo mặc định. Nó chỉ là, theo mặc định (cho tương thích ngược - blek) Perl sẽ xuất các ký tự 128-255 như thế nào? thay vì Unicode, trừ khi bạn đặc biệt không nói với nó. –

+0

Ngoài ra một số trình chỉnh sửa (ví dụ: vim) tự động phát hiện xem tệp có phải là UTF-8 hay không và cố gắng hiển thị nó đúng cách bất kỳ mã hóa nào. Việc mở một tệp trong trình chỉnh sửa không phải là một thử nghiệm đáng tin cậy. (Cũng có khá nhiều trình soạn thảo thực sự chạy trong - có thể bị lỗi - thiết bị đầu cuối). Ngoài ra, theo nghĩa đen, nó trả lời câu hỏi OP không chính xác. –

-3

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

Điều này có lẽ sẽ cho thấy rằng vỏ của bạn không được sử dụng một miền địa phương utf-8.

+0

Thực ra, nó được đặt thành utf-8. Vấn đề là tôi đã xuất ra STDOUT mà không cần đặ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 bạn để xuất dữ liệu chính xác trước khi bạn có thể lo lắng về cách trình mô phỏng thiết bị đầu cuối của bạn diễn giải nó. – jrockway

75

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

Ví dụ: dưới đây trình bày STDOUT, STDIN & STDERR sử dụng UTF-8 ....

use open qw/:std :utf8/; 
+1

Cũng tốt. Tôi sẽ +1 nhưng tôi đã bỏ phiếu cho ngày hôm nay. –

+1

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

57

TMTOWTDI, chọn phương pháp thích 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 vì vậy tôi không phải suy nghĩ về nó.

Trong environment:

export PERL_UNICODE=SDL 

trên command line:

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 qua các nhân open pragma:

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

'-CSDL' đã làm việc cho tôi ở nơi' binmode' một mình thì không. – beerbajay

+1

+1 cho câu trả lời toàn diện; lưu ý rằng 'SDL' được ngụ ý cả với' -C' và 'PERL_UNICODE'. 'Use open ': locale'' pragma cũng đáng nhắc tới, bởi vì nó tương đương với kịch bản' -C' và 'export PER_UNICODE ='. Bất kỳ trong số 3 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ù tệp hoặc stdin/stdout/stderr), giả sử ngôn ngữ của môi trường của bạn là dựa trên UTF8. Cuối cùng, để xử lý mã _source_ là UTF8, hãy sử dụng 'use utf8;' pragma. – mklement0

0

Cảm ơn, cuối cùng có một giải pháp để không đặt utf8 :: encode trên tất cả các mã. Để tổng hợp và toàn diện cho các trường hợp khác, như viết và đọc tập tin trong utf8 và cũng làm việc với LoadFile của một file 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 
Các vấn đề liên quan