Perl Language
유니 코드
수색…
비고
파일 이름 인코딩에 대한 경고
Filename Encoding은 특정 플랫폼 뿐만 아니라 파일 시스템과 도 관련이 있음을 언급 할 가치가 있습니다.
주어진 파일 이름을 인코딩하고 쓸 수 있기 때문에, 나중에 같은 파일 이름을 읽기 위해 열려고해도 똑같은 이름이 붙을 것이라고 가정하는 것은 전적으로 안전합니다 (그러나 대개 그렇습니다).
예를 들어, 유니 코드를 지원하지 않는 FAT16
과 같은 파일 시스템에 쓰면 파일 이름이 자동으로 ASCII 호환 형식으로 변환 될 수 있습니다.
그러나 명시 적 이름 지정으로 작성하고 읽고 쓸 수있는 파일이 다른 호출을 통해 쿼리 될 때 동일한 호출을 받았다고 가정하는 것이 훨씬 안전하지 않습니다. 예를 들어 readdir
은 지정한 파일 이름과 다른 바이트를 반환 할 수 open
.
VAX와 같은 일부 시스템에서는 파일 확장자 가 OS에 의해 변경 될 수 있기 때문에 readdir
이 foo.bar
처럼 파일 이름에 대해 open
과 함께 지정한 동일한 파일 이름을 반환한다고 항상 가정 할 수도 없습니다.
또한 UNIX에는 /
와 \0
만 제외하고 OS에서 허용하는 파일 이름에 대해 매우 자유로운 일련의 합법적 인 문자 집합이 있습니다. Windows에서는 파일 이름에서 금지 된 특정 문자 범위가 있으며 오류가 발생할 수 있습니다.
여기에 많은주의를 기울이고, 선택이 있다면 파일 이름으로 멋진 트릭을 피하고 사용하는 멋진 트릭이 일관성 이 있는지 확인하기위한 테스트를 항상 거쳐야합니다.
CPAN
용 코드를 작성하는 경우와 같이 제어 할 수없는 플랫폼에서 실행되도록 의도 된 코드를 작성하는 경우 두 배의주의를 기울여야 하며 사용자 기반의 최소 5 %가 선택에 의해, 우연히 또는 통제를 벗어난 권한으로 고대 또는 부러진 기술을 사용하고, 이들이 버그를 만들기 위해 공모 할 것입니다.
: 인코딩 (utf8) vs : utf8
UTF-8은 Perl에서 문자열을 표현하기위한 내부 형식 중 하나이기 때문에 인코딩 / 디코딩 단계를 건너 뛸 수 있습니다. 대신 :encoding(utf-8)
대신 데이터가 이미 UTF-8 인 경우 :utf8
사용할 수 있습니다. :utf8
은 출력 스트림과 함께 안전하게 사용할 수 있지만 입력 스트림의 경우 잘못된 바이트 시퀀스가있을 때 내부 불일치가 발생하므로 위험 할 수 있습니다. 또한, :utf8
을 입력으로 사용하면 보안 위반이 발생할 수 있으므로 :encoding(utf-8)
을 사용하는 것이 좋습니다.
추가 정보 : 인코딩과 utf8의 차이점은 무엇입니까?
UTF-8 대 UTF8 대 UTF8
Perl v5.8.7
부터 "UTF-8"
(대시 포함)은 엄격하고 보안을 고려한 형태로 UTF-8을 의미하는 반면 "utf8"
은 자유롭고 자유로운 형식의 UTF-8을 의미합니다.
예를 들어 "utf8"
은 0xFFFFFFFF
와 같이 유니 코드에없는 코드 포인트에 사용할 수 있습니다. 그에 상응하여 "\x{FE}\x{83}\x{BF}\x{BF}\x{BF}\x{BF}\x{BF}"
와 같은 잘못된 UTF-8 바이트 시퀀스가 "UTF-8"
인코딩은 유효한 유니 코드 범위를 벗어난 코드 포인트로 디코딩 할 수 없으며 대신 대체 문자 ( 0xFFFD
)를 제공하지만 "utf8"
사용할 때는 잘못된 유니 코드 (유효한 Perl) 코드 포인트 ( 0xFFFFFFFF
)가 사용됩니다.
인코딩 이름은 대소 문자를 구분하지 않으므로 "UTF8"
은 "utf8"
과 동일합니다 (즉 , 엄격하지 않은 변형).
세부 정보 : UTF-8 vs. utf8 vs. UTF8
더 많은 독서
Perl의 유니 코드 처리에 대한 자세한 내용은 다음 소스에서 자세히 설명합니다.
- 퍼런 코드
- 퍼 루니 투트
- 펄 루니 인트로
- 퍼 루니 파크
- 퍼니닉
- utf8 pragma
- 유니 코드 문자열 기능
- 오픈 프라그 마
- PerlIO
- PerlIO :: 인코딩
- 개방 기능
- 인코딩
- perlrun - 명령 행 스위치
- 6 장, Perl 프로그래밍
stackoverflow.com의 게시물 (주의 : 최신이 아닐 수도 있음) :
유튜브 동영상 :
- 2016 년 YAPC에서 리카르도 (Ricardo Signes) 의 백만 달러짜리 캐릭터 .
파일 이름 만들기
다음 예제는 UTF-8 인코딩을 사용하여 디스크의 파일 이름 (및 디렉토리 이름)을 나타냅니다. 다른 인코딩을 사용하려면 Encode::encode(...)
사용해야 Encode::encode(...)
.
use v5.14;
# Make Perl recognize UTF-8 encoded characters in literal strings.
# For this to work: Make sure your text-editor is using UTF-8, so
# that bytes on disk are really UTF-8 encoded.
use utf8;
# Ensure that possible error messages printed to screen are converted to UTF-8.
# For this to work: Check that your terminal emulator is using UTF-8.
binmode STDOUT, ':utf8';
binmode STDERR, ':utf8';
my $filename = 'æ€'; # $filename is now an internally UTF-8 encoded string.
# Note: in the following it is assumed that $filename has the internal UTF-8
# flag set, if $filename is pure ASCII, it will also work since its encoding
# overlaps with UTF-8. However, if it has another encoding like extended ASCII,
# $filename will be written with that encoding and not UTF-8.
# Note: it is not necessary to encode $filename as UTF-8 here
# since Perl is using UTF-8 as its internal encoding of $filename already
# Example1 -- using open()
open ( my $fh, '>', $filename ) or die "Could not open '$filename': $!";
close $fh;
# Example2 -- using qx() and touch
qx{touch $filename};
# Example3 -- using system() and touch
system 'touch', $filename;
# Example4 -- using File::Touch
use File::Touch;
eval { touch( $filename ) }; die "Could not create file '$filename': $!" if $@;
파일 이름 읽기
Perl은 기본 함수 나 모듈에 의해 반환 된 파일 이름을 디코딩하지 않습니다. 파일명을 나타내는 문자열은 Perl이 유니 코드로 인식 할 수 있도록 항상 명시 적으로 해독되어야합니다.
use v5.14;
use Encode qw(decode_utf8);
# Ensure that possible error messages printed to screen are converted to UTF-8.
# For this to work: Check that you terminal emulator is using UTF-8.
binmode STDOUT, ':utf8';
binmode STDERR, ':utf8';
# Example1 -- using readdir()
my $dir = '.';
opendir(my $dh, $dir) or die "Could not open directory '$dir': $!";
while (my $filename = decode_utf8(readdir $dh)) {
# Do something with $filename
}
close $dh;
# Example2 -- using getcwd()
use Cwd qw(getcwd);
my $dir = decode_utf8( getcwd() );
# Example3 -- using abs2rel()
use File::Spec;
use utf8;
my $base = 'ø';
my $path = "$base/b/æ";
my $relpath = decode_utf8( File::Spec->abs2rel( $path, $base ) );
# Note: If you omit $base, you need to encode $path first:
use Encode qw(encode_utf8);
my $relpath = decode_utf8( File::Spec->abs2rel( encode_utf8( $path ) ) );
# Example4 -- using File::Find::Rule (part1 matching a filename)
use File::Find::Rule;
use utf8;
use Encode qw(encode_utf8);
my $filename = 'æ';
# File::Find::Rule needs $filename to be encoded
my @files = File::Find::Rule->new->name( encode_utf8($filename) )->in('.');
$_ = decode_utf8( $_ ) for @files;
# Example5 -- using File::Find::Rule (part2 matching a regular expression)
use File::Find::Rule;
use utf8;
my $pat = '[æ].$'; # Unicode pattern
# Note: In this case: File::Find::Rule->new->name( qr/$pat/ )->in('.')
# will not work since $pat is Unicode and filenames are bytes
# Also encoding $pat first will not work correctly
my @files;
File::Find::Rule->new->exec( sub { wanted( $pat, \@files ) } )->in('.');
$_ = decode_utf8( $_ ) for @files;
sub wanted {
my ( $pat, $files ) = @_;
my $name = decode_utf8( $_ );
my $full_name = decode_utf8( $File::Find::name );
push @$files, $full_name if $name =~ /$pat/;
}
참고 : 파일 이름에서 유효하지 않은 UTF-8이 염려되는 경우 위 예제에서 decode_utf8( ... )
을 decode( 'utf-8', ... )
로 대체해야합니다. 때문이다 decode_utf8( ... )
동의어이다 decode( 'utf8', ... )
및 인코딩 된 차이가 utf-8
및 utf8
(참조 소견 자세한 내용은 아래)를 여기서 utf-8
더 utf8
보다 수용 할 수있는 것에 엄격한
한 줄짜리 명령 줄 스위치
utf8 pragma 사용
one-liner에서 utf8
pragma를 사용하려면 perl 인터프리터를 -Mutf8
옵션과 함께 호출해야합니다.
perl -Mutf8 -E 'my $人 = "human"; say $人'
-C 스위치를 사용한 유니 코드 처리
-C
명령 행 플래그를 사용하여 유니 코드 기능을 제어 할 수 있습니다. 그 뒤에 옵션 문자 목록을 올릴 수 있습니다.
표준 I / O
-
I
-STDIN
은 UTF-8 이 될 것입니다. -
O
-STDOUT
은 UTF-8 형식입니다. -
E
-STDERR
은 UTF-8 이 될 것입니다. -
S
-IOE
약자로, 표준 I / O 스트림은 UTF-8
echo "Ματαιότης ματαιοτήτων" | perl -CS -Mutf8 -nE 'say "ok" if /Ματαιότης/'
스크립트의 주장
-
A
-@ARGV
를 UTF-8 인코딩 된 문자열의 배열로 처리합니다.
perl -CA -Mutf8 -E 'my $arg = shift; say "anteater" if $arg eq "муравьед"' муравьед
기본 PerlIO 계층
-
i
- UTF-8 은 입력 스트림의 기본 PerlIO 레이어입니다. -
o
- UTF-8 은 출력 스트림을위한 기본 PerlIO 레이어입니다. -
D
-io
대한 속기
perl -CD -Mutf8 -e 'open my $fh, ">", "utf8.txt" or die $!; print $fh "개미 조심해"'
-M
및 -C
스위치를 결합 할 수 있습니다.
perl -CASD -Mutf8 -E 'say "Ματαιότης ματαιοτήτων\n"';
표준 I / O
표준 I / O 파일 핸들 ( STDIN
, STDOUT
및 STDERR
)에 사용할 인코딩은 binmode
사용하여 핸들마다 별도로 설정할 수 있습니다.
binmode STDIN, ':encoding(utf-8)';
binmode STDOUT, ':utf8';
binmode STDERR, ':utf8';
참고 : 일반적으로 읽는 사람은 :encoding(utf-8)
:utf8
선호합니다 :encoding(utf-8)
자세한 내용은 비고 참조).
또는 open
pragma를 사용할 수 있습니다.
# Setup such that all subsequently opened input streams will use ':encoding(utf-8)'
# and all subsequently opened output streams will use ':utf8'
# by default
use open (IN => ':encoding(utf-8)', OUT => ':utf8');
# Make the (already opened) standard file handles inherit the setting
# given by the IO settings for the open pragma
use open ( :std );
# Now, STDIN has been converted to ':encoding(utf-8)', and
# STDOUT and STDERR have ':utf8'
또는, 아직 열지 않은 파일 핸들과 표준 파일 핸들을 모두 설정하려면 :encoding(utf-8)
을 사용하십시오 :encoding(utf-8)
:
use open qw( :encoding(utf-8) :std );
파일 핸들
open ()로 인코딩 설정하기
텍스트 파일을 열 때 3 개의 인자로 open()
명시 적으로 인코딩 할 수 있습니다. 파일 핸들에 첨부 된이 엔코더 또는 디코더를 "I / O 레이어"라고합니다.
my $filename = '/path/to/file';
open my $fh, '<:encoding(utf-8)', $filename or die "Failed to open $filename: $!";
:utf8
과 :encoding(utf-8)
의 차이점에 대한 설명 은 참고를 참조하십시오.
binmode ()로 인코딩 설정하기
또는 binmode ()를 사용하여 개별 파일 핸들의 인코딩을 설정할 수 있습니다.
my $filename = '/path/to/file';
open my $fh, '<', $filename or die "Failed to open $filename: $!";
binmode $fh, ':encoding(utf-8)';
오픈 프라그 마
별도로 각 파일 핸들의 인코딩을 설정하지 않으 open
pragma를 사용하여이 pragma의 어휘 범위 내에서 open()
함수 및 유사한 연산자에 대한 이후의 모든 호출에서 사용되는 기본 I / O 레이어를 설정할 수 있습니다.
# Set input streams to ':encoding(utf-8)' and output streams to ':utf8'
use open (IN => ':encoding(utf-8)', OUT => ':utf8');
# Or to set all input and output streams to ':encoding(utf-8)'
use open ':encoding(utf-8)';
명령 행으로 인코딩 설정 -C 플래그
마지막으로 UTF-8을 기본 I / O 레이어로 적용하는 -CD
플래그를 사용하여 perl 인터프리터를 실행할 수도 있습니다. 그러나이 옵션은 예측하거나 제어 할 수없는 특정 사용자 동작에 의존하기 때문에 피해야합니다.
utf8 pragma : 소스에서 유니 코드 사용
utf8
pragma는 소스 코드가 UTF-8로 해석됨을 나타냅니다. 물론 이것은 텍스트 편집기가 UTF-8로 소스를 저장하는 경우에만 작동합니다.
자, 문자열 리터럴은 임의의 유니 코드 문자를 포함 할 수 있습니다. 식별자는 유니 코드를 포함 할 수 있지만 단어와 유사한 문자 만 포함 할 수 있습니다 (자세한 내용은 perldata 및 perlrecharclass 참조).
use utf8;
my $var1 = '§я§©😄'; # works fine
my $я = 4; # works since я is a word (matches \w) character
my $p§2 = 3; # does not work since § is not a word character.
say "ya" if $var1 =~ /я§/; # works fine (prints "ya")
참고 : 터미널에 텍스트를 인쇄 할 때 UTF-8을 지원하는지 확인하십시오. *
출력과 소스 인코딩간에 복잡하고 반 직관적 인 관계가있을 수 있습니다. UTF-8 터미널에서 실행 utf8
면 utf8
pragma를 추가하면 문제가 발생할 수 있습니다.
$ perl -e 'print "Møøse\n"'
Møøse
$ perl -Mutf8 -e 'print "Møøse\n"'
M��se
$ perl -Mutf8 -CO -e 'print "Møøse\n"'
Møøse
첫 번째 경우에 Perl은 문자열을 원시 바이트로 처리하여이를 인쇄합니다. 이 바이트들은 유효한 UTF-8 일 때 Perl이 실제로 어떤 문자인지를 알지 못하더라도 (예 : length("Møøse")
는 5가 아닌 7을 반환합니다 length("Møøse")
. 일단 -Mutf8
을 추가하면 Perl은 UTF-8 소스를 문자로 올바르게 디코딩하지만, 출력은 기본적으로 Latin-1 모드이며 Latin-1을 UTF-8 터미널에 인쇄하는 것은 작동하지 않습니다. -CO
를 사용하여 STDOUT
을 UTF-8로 전환 할 때만 출력이 정확합니다.
use utf8
표준 I / O 인코딩이나 파일 핸들에 영향을 미치지 않습니다!
잘못된 UTF-8 처리
잘못된 UTF-8 읽기
UTF-8로 인코딩 된 데이터를 읽을 때 UTF-8로 인코딩 된 데이터가 유효하지 않거나 형식이 잘못 될 수 있다는 사실을 알고 있어야합니다. 그러한 데이터는 일반적으로 프로그램에 의해 받아 들여지지 않아야합니다 (자신이하는 일을 알지 못한다면). 예기치 않게 잘못된 형식의 데이터가 발생하면 다른 동작을 고려할 수 있습니다.
- 스택 추적 또는 오류 메시지를 인쇄하고 정상적으로 프로그램을 중단하거나
- 잘못된 바이트 시퀀스가 나타난 위치에 대체 문자를 삽입하고 STDERR에 경고 메시지를 인쇄하고 아무 일도 일어나지 않을 때 계속해서 읽습니다.
기본적으로 Perl은 글리치 인코딩에 대해 warn
하지만 프로그램을 중단하지는 않습니다. UTF-8 경고를 치명적으로 만들어 프로그램을 중단시킬 수 있지만 치명적인 경고 의주의 사항을 알고 있어야합니다.
다음 예제는 ISO 8859-1 인코딩의 3 바이트를 디스크에 씁니다. 그런 다음 다시 바이트를 UTF-8로 인코딩 된 데이터로 다시 읽으려고합니다. 바이트 중 하나 인 0xE5
는 유효하지 않은 UTF-8 1 바이트 시퀀스입니다.
use strict;
use warnings;
use warnings FATAL => 'utf8';
binmode STDOUT, ':utf8';
binmode STDERR, ':utf8';
my $bytes = "\x{61}\x{E5}\x{61}"; # 3 bytes in iso 8859-1: aåa
my $fn = 'test.txt';
open ( my $fh, '>:raw', $fn ) or die "Could not open file '$fn': $!";
print $fh $bytes;
close $fh;
open ( $fh, "<:encoding(utf-8)", $fn ) or die "Could not open file '$fn': $!";
my $str = do { local $/; <$fh> };
close $fh;
print "Read string: '$str'\n";
치명적인 경고와 함께 프로그램이 중단됩니다.
utf8 "\xE5" does not map to Unicode at ./test.pl line 10.
10 번째 줄은 여기에서 두 번째 마지막 <$fh>
파일에서 한 줄을 읽으 려 할 때 <$fh>
가있는 줄 부분에서 오류가 발생합니다.
위의 프로그램에서 경고를 치명적으로 만들지 않으면 Perl은 여전히 경고를 출력합니다. 그러나이 경우 스트림에 4 개의 문자 \xE5
를 삽입하여 조작 된 바이트 0xE5
를 복구하려고 시도하고 다음 바이트로 계속 진행합니다. 결과적으로 프로그램은 다음을 인쇄합니다.
Read string: 'a\xE5a'