2012-04-10 9 views
3

ユニコード問題で困惑したときに、クエリ文字列の解析をテストする例を書き上げようとしています。つまり、文字「オメガ」(Ω)は正しくデコードされていないようです。Perlでのクエリ文字列のユニコード処理の処理

  • のUnicode: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; 

とテストの出力:

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 

それはエンコードがここに破損する可能性が:: URIのように私には見えますが、URI ::エスケープに切り替えるとuri_unescape機能を使用して同じことを報告しますエラー。私は何が欠けていますか?

+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"です。これは、比較すると、後者が3文字の長さのラテン1文字列としてアップグレードされるため、失敗します。

uri_decodeの後に手動で入力値をEncode::decode_utf8にデコードするか、エンコードされたutf8バイトシーケンスを比較する必要があります。あなたが例えば、文字にUTF-8オクテットから自分をデコードする必要がありますので

5

URIのエスケープは、オクテットを表し、文字エンコーディングについて何も知らない:

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

私はあなたのためにWhy does modern Perl avoid UTF-8 by default?を見てすることをお勧めしますこのトピックに関する徹底的な議論。

私はそこの議論に追加します。

  • あなたは、ページ上の奇妙なグリフの多くを気づくでしょう。これは著者の意図的なものでした。
  • 私はスレッドで推奨されているSymbolaフォントを試しましたが、Win 7.YMMVではひどく見えました。
  • 読書現代のPerlはなぜデフォルトでUTF-8を避けるのですか?があまりにも頻繁にあなたの人生の選択肢にうつ病と長引く疑いにつながる可能性があります。
+1

これまでに私が読んだことがあり、チクリスの反応は素晴らしいと思います。 – Ovid

4

この問題は、問題の独自の説明で間違った詳細が見られることがあります。あなたが扱っていることは本当にです:

  • Unicodeのコードポイント:U + 2126コードポイントの
  • UTF-8エンコーディング:コードポイントのUTF-8エンコーディングの\ XE2 \ X84 \ xa6
  • URIエンコーディング:% E2%84%A6

問題は、エンコードされていないエンコードの1つだけです。

解決策は既に提示されています。私は別の説明をしたかっただけです。

関連する問題