2010-06-03 3 views
8

어떻게 펄 문자열이 내부적으로 표현 되었습니까? 어떤 인코딩이 사용됩니까? 어떻게하면 다른 인코딩을 제대로 처리 할 수 ​​있습니까?Perl 문자열 내부

필자는 오랫동안 perl을 사용 해왔지만 다른 인코딩에서는 많은 문자열 처리를 포함하지 않았고, 인코딩과 관련이있는 사소한 문제가 발생했을 때 나는 보통 무속 행동.

지금까지 필자는 perl 문자열을 바이트 순서로 생각했는데, 이는 필자의 작업에 매우 적합했습니다. 이제 UTF-8로 인코딩 된 파일을 처리해야하는데 여기에서 문제가 발생합니다.

print $contents; 

그리고 나는 두 가지를 얻을 :

open(my $in, '<', $ARGV[0]) or die "cannot open file $ARGV[0] for reading"; 
binmode($in, ':utf8'); 

my $contents; 

{ 
    local $/; 
    $contents = <$in>; 
} 

close($in); 

다음 간단하게 인쇄 :

는 첫째,이 같은 문자열로 파일을 읽을 경고 Wide character in print at <scriptname> line <n> 및 콘솔에서 쓰레기를. 그래서 펄 문자열은 "넓이"가 될 수있는 "문자"개념을 가지고 있다고 결론을 내릴 수 있습니다. 그러나 인쇄 될 때 이러한 "와이드"문자는 단일 "문자"가 아닌 여러 바이트로 콘솔에 표현됩니다. (왜 지금까지 이진 파일을 사용하여 이전의 모든 경험이 "문자"문제없이 작동하는 것을 기대했던 것일까?)

왜 콘솔에서 가비지가 표시됩니까? perl이 문자열을 문자로 저장하는 경우, 콘솔 인코딩을 찾고 텍스트를 제대로 인쇄하는 데 큰 문제가 없다고 생각합니다. (나는 Windows를 사용한다.)

perl이 가변 폭 문자 시퀀스 (예 : 동일한 UTF-8 인코딩 사용)로 문자열을 저장하는 경우 왜 이렇게 했습니까? 내 C 경험에서 다루는 문자열은 PAIN입니다.

업데이트.

테스트 용 컴퓨터 두 대를 사용합니다. 영어 팩을 설치 한 상태에서 Windows 7 x64를 실행하지만 러시아 국가 별 설정으로 ActivePerl 5.10.1 x64와 함께 cp866를 OEM 코드 페이지로, cp1251을 ANSI로 사용합니다. 다른 하나는 Cygwin Perl 5.10.0을 사용하여 Windows XP 32 비트 러시아어 현지화를 실행합니다.

링크 덕분에 이제는 무슨 일이 일어나고 어떻게해야하는지에 대해 훨씬 더 확실하게 이해할 수있게되었습니다.

답변

4

파일에서 읽기 전에 utf8을 설정하면 자동으로 바이트가 내부 인코딩으로 디코딩됩니다. (UTF-8이기도하지만 당신은 알 필요가없고 의지해서는 안됩니다.)

인쇄하기 전에 문자를 다시 바이트로 인코딩해야합니다.

use Encode; 
utf8::encode($contents); 

또한 유니 코드 이외의 인코딩에는 encode의 두 가지 인수 형식이 있습니다. (그 문장은 너무 많이 울립니다.)

여기는 좋은 참고 자료입니다. (더 많았지 만 첫 번째 게시물입니다.) perlunitut과 Joel on Software의 유니 코드 기사를 확인하십시오. 그렇지 않으면 그냥 유니 코드 아니기 때문에

http://www.ahinea.com/en/tech/perl-unicode-struggle.html

아, 그리고, 멀티 바이트 문자열을 사용해야합니다.

+0

다중 바이트 문자열은 가변 폭 인코딩을 의미합니다. – n0rd

+0

어쨌든 왜 변환을 명시 적으로해야합니까? 입력 데이터 인코딩을 지정 했으므로 추가 단계를 수행해야하는 이유는 무엇입니까? – n0rd

+2

입력 인코딩을 지정했습니다. 너는 너를 해. 그런 다음 출력 인코딩을 지정합니다. 내가 언급 한 기사는 더 잘 설명한다. 나는 생각해야한다. – dylan

2

실제로 사용하는 버전 및 설치된 언어 패키지에 따라 실제 Windows 및 Perl 버전을 언급해야합니다.

펄이 내부적으로 문자열을 표현하기 위해 논리적으로 전체 문자를 사용 -
그렇지 않으면 먼저 PerlUnicode 매뉴얼을 읽어보세요.

귀하의 진술을 확인합니다.

Windows가 모든 UTF8 문자를 완전히 설치하지 않으므로이 문제가 발생할 수 있습니다. 추가 언어 패키지를 설치해야 할 수도 있습니다.

+0

두 번째 문장에서 두 번째 문장은 전혀 이해가되지 않습니다. 글꼴을 참조하는 것처럼 보이지만 이는 인코딩과 관련이 없습니다. – daxim

4

Perl 문자열은 내부적으로 8 비트 바이트 지향 인코딩 또는 UTF-8 인코딩 중 하나에 저장됩니다. 역 비교를 위해 별도로 지정하지 않는 한 모든 I/O 및 문자열은 기본 인코딩으로되어 있습니다. 네이티브 인코딩은 일반적으로 8 비트 ASCII이지만, use locale으로 변경할 수 있습니다.

샘플에서는 입력 핸들에서 binmode를 호출하여 :utf8 의미론을 사용하도록 변경합니다. 이것의 한 가지 효과는이 핸들에서 읽은 모든 문자열이 UTF-8로 인코딩된다는 것입니다. print은 기본적으로 STDOUT에 쓰고 STDOUT은 기본 인코딩 된 문자를 기본으로합니다.

Perl은 올바른 작업을 수행하기 위해 UTF-8 문자열을 네이티브 인코딩 된 출력으로 보낼 수 있지만 해당 핸들에 첨부 된 인코딩이없는 경우 멀티 바이트 출력 방법을 추측해야합니다 문자와 거의 틀림없이 추측 할 것입니다. 이것이 경고의 의미이며, 멀티 바이트 문자가 단일 바이트 문자 만 예상되는 스트림으로 전송 되었기 때문에 결과적으로 문자가 번역에서 손상되었을 가능성이 높습니다.

dylan에서 언급 한 Encode 모듈을 사용하여 UTF-8 데이터를 안전하게 인쇄 할 수있는 1 바이트 문자 세트로 변환하거나 STDOUT에 첨부 된 것이 무엇이든 UTF-8은 binmode(STDOUT, ':utf8');을 사용하여 STDOUT으로 전송 된 모든 데이터를 UTF-8로 보내도록 Perl에 알릴 수 있습니다.

+0

기본 인코딩이 8 비트 ASCII (또는 다른 8 비트 인코딩) 인 경우 Perl이 UTF-8 문자열을 원시 바이트로 인쇄하는 이유 (즉, 인쇄 된 문자열의 각 키릴 문자에 대해 콘솔에 두 개의 문자 인쇄) 원래 문자열에서와 똑같은 문자 양을 가진 해당 인코딩? – n0rd

+1

@ n0rd UTF-8 문자열은 perl 관점의 바이트가 아니며 문자입니다. 이 IIRC의 이상한 결과는 인코딩이 정의되지 않은 핸들로 인쇄 될 때 255보다 큰 유니 코드 코드 포인트를 더 낮은 8 비트로 자릅니다. –

관련 문제