2012-04-10 3 views
3

유니 코드 문제로 어려움을 겪었을 때 쿼리 문자열 구문 분석 테스트 예제를 작성하려고합니다. 즉, 문자 "Omega"(Ω)는 올바르게 디코딩되지 않는 것 같습니다.Perl에서 쿼리 문자열 유니 코드 처리하기

  • 유니 코드 : U 2126을
  • 3 바이트 시퀀스 + : \ XE2 \ X84 \ xa6
  • URI 인코딩 : % E2의 % 84 % A6

그래서 내가 쓴이 테스트 프로그램 확인 URI :: Encode를 사용하여 유니 코드 쿼리 문자열을 "디코딩"할 수있었습니다.

use strict;                                          
use warnings; 
use utf8::all; # use before Test::Builder clones STDOUT, etc. 
use URI::Encode 'uri_decode'; 
use Test::More; 

sub parse_query_string { 
    my $query_string = shift; 
    my @pairs = split /[&;]/ => $query_string; 

    my %values_for; 
    foreach my $pair (@pairs) { 
     my ($key, $value) = split(/=/, $pair); 
     $_ = uri_decode($_) for $key, $value; 
     $values_for{$key} ||= []; 
     push @{ $values_for{$key} } => $value; 
    } 
    return \%values_for; 
} 

my $omega = "\N{U+2126}"; 
my $query = parse_query_string('alpha=%E2%84%A6'); 
is_deeply $query, { alpha => [$omega] }, 'Unicode should decode correctly'; 

diag $omega; 
diag $query->{alpha}[0]; 

done_testing; 

그리고 테스트의 출력은 : URI :: 인코딩 여기에 깨진하지만, 탈출 :: URI로 전환하고 uri_unescape 기능을 사용하여 동일한보고 할 수있다처럼

query.t .. 
not ok 1 - Unicode should decode correctly 
# Failed test 'Unicode should decode correctly' 
# at query.t line 23. 
#  Structures begin differing at: 
#   $got->{alpha}[0] = 'â¦' 
#  $expected->{alpha}[0] = 'Ω' 
# Ω 
# ⦠
1..1 
# Looks like you failed 1 test of 1. 
Dubious, test returned 1 (wstat 256, 0x100) 
Failed 1/1 subtests 

Test Summary Report 
------------------- 
query.t (Wstat: 256 Tests: 1 Failed: 1) 
    Failed test: 1 
    Non-zero exit status: 1 
Files=1, Tests=1, 0 wallclock secs (0.03 usr 0.01 sys + 0.05 cusr 0.00 csys = 0.09 CPU) 
Result: FAIL 

그것은 나에게 보인다 오류. 내가 뭘 놓치고 있니?

+1

'CGI' 모듈은 [pragma import'-utf8' 자동으로 입력을 해독합니다] (http://p3rl.org/CGI#utf8)를 제공합니다. 이것은 의도 한대로 동작합니다 :'perl -e 'use CGI qw (-utf8); my $ cgi = CGI-> new ("alpha = % E2 % 84 % A6"); Devel :: Peek을 사용하십시오. $ cgi-> param ("alpha")''문서에 언급 된주의 사항에주의하십시오. – daxim

답변

7

URI 인코딩 된 문자는 단순히 utf-8 시퀀스를 나타내며 URI :: Encode 및 URI :: Escape는이를 단순히 utf-8 바이트 문자열로 디코딩하며 둘 다 UTF-8로 바이트 코드를 디코딩하지 않습니다. 일반적인 URI 디코딩 라이브러리로서 올바른 행동).

다른 식으로 말하자면 코드는 기본적으로 다음과 같습니다. is "\N{U+2126}", "\xe2\x84\xa6" 비교할 때 perl은 후자를 3 자 길이의 latin-1 문자열로 업그레이드하므로 실패합니다.

uri_decode 이후에 수동으로 입력 값을 Encode::decode_utf8으로 디코딩하거나 대신 인코딩 된 utf8 바이트 시퀀스를 비교해야합니다.

5

URI의 이스케이프는, 예를 들어 옥텟을 대표하고 문자를 UTF-8 옥텟에서 자신을 디코딩 할 수 있도록, 문자 인코딩에 대해 아무것도 모르는 :

$_ = decode_utf8(uri_decode($_)) for $key, $value; 
0

당신이 Why does modern Perl avoid UTF-8 by default?에서보기를위한이 것을 권 해드립니다 이 주제에 대한 철저한 토론

나는이 토론에 추가합니다 :

  • 당신은 페이지의 이상한 상형 문자를 많이 알 수 있습니다. 이것은 저자 측에서 의도적이었습니다.
  • 스레드에서 권장되는 Symbola 글꼴을 사용해 보았는데 Win 7에서 끔찍한 느낌이었습니다.
  • 읽기 현대 Perl은 기본적으로 UTF-8을 사용하지 않는 이유는 무엇입니까? 너무 자주 빈번히 우울증에 빠지면 삶의 선택에 대한 의구심이 생길 수 있습니다.
+1

나는 전에 그것을 읽었으며 나는 tchrist의 반응이 뛰어나다 고 생각한다. – Ovid

4

문제는 자신의 설명에서 잘못된 세부 사항으로 볼 수 있습니다.당신이 다루고있는 것은 정말 :

  • 유니 코드 코드 포인트 : U 코드 포인트의 + 2126
  • UTF-8 인코딩 : \ XE2 \ X84 \ xa6
  • 코드 포인트의 UTF-8 인코딩의
  • URI 인코딩 % E2 % 84 % A6

문제는 단지 인코딩 중 하나를 undid한다는 것입니다.

해결책은 이미 제시되었습니다. 나는 단지 다른 설명을하고 싶었다.