2013-09-19 4 views
0

Я пытаюсь убежать от арабского к LWP :: UserAgent. Я проверяю это с помощью скрипта ниже:perl uri_escape_utf8 с арабским

my $files = "/home/root/temp.txt"; 
unlink ($files); 
open (OUTFILE, '>>', $files); 
my $text = "ضثصثضصثشس"; 
print OUTFILE uri_escape_utf8($text)."\n"; 
close (OUTFILE); 

Однако, это, кажется, вызывает следующее:

%C3%96%C3%8B%C3%95%C3%8B%C3%96%C3%95%C3%8B%C3%94%C3%93 

, которая не является правильным. Любые указания на то, что мне нужно сделать, чтобы избежать этого правильно?

Благодарим за помощь.

С уважением,

Olli

+0

Является ли ваш файл Perl кодированным как UTF-8? Вы использовали utf8? Если я это сделаю, я получаю «% D8% B6% D8% AB% D8% B5% D8% AB% D8% B6% D8% B5% D8% AB% D8% B4% D8% B3' - это правильно? (Это округляет правильно) – amon

ответ

2

Perl consideres ваш исходный файл должен быть закодирован в Latin-1, пока вы не скажете ему use utf8. Если мы это сделаем, строка "ضثصثضصثشس" не содержит некоторых перемежающихся байтов, а скорее представляет собой строку codepoints.

uri_escape_utf8 ожидает строку кодовых точек (не байтов!), Кодирует их, а затем URI-экранирует их. Ergo, правильная вещь, чтобы сделать

use utf8; 
use URI::Escape; 
print uri_escape_utf8("ضثصثضصثشس"), "\n"; 

Выход: %D8%B6%D8%AB%D8%B5%D8%AB%D8%B6%D8%B5%D8%AB%D8%B4%D8%B3


Если мы не use utf8, то uri_escape_utf8 получает строку байтов (которые случайно закодированную в UTF8), так что мы должны использовали uri_escape:

die "This is the wrong way to do it"; 
use URI::Escape; 
print uri_escape("ضثصثضصثشس"), "\n"; 

, который производит такой же результат, как и выше, - но только случайно.

Использование uri_escape_utf8 ти байтовой строки (что бы расшифровывает к арабским буквам) производит совершенно неправильно

%C3%98%C2%B6%C3%98%C2%AB%C3%98%C2%B5%C3%98%C2%AB%C3%98%C2%B6%C3%98%C2%B5%C3%98%C2%AB%C3%98%C2%B4%C3%98%C2%B3 

, потому что это фактически дважды кодирует данные. Это то же самое, как

use utf8; 
use URI::Escape; 
use Encode; 
print uri_escape(encode "utf8", encode "utf8", "ضثصثضصثشس"), "\n"; 

Edit: Так вы использовали CP-1256, которая является непереносимой одного кодирования байт. Он не может кодировать произвольные символы Юникода, поэтому его следует избегать вместе с другими кодировками до Unicode. Вы не объявили свою кодировку, поэтому perl считает, что вы имели в виду латинский-1. Это означает, что то, что вы видели как "ضثصثضصثشس", было фактически байтовым потоком D6 CB D5 CB D6 D5 CB D4 D3, который декодирует некоторый нецензурный барахл в латинском-1.

Редактировать: Итак, вы хотите декодировать аргументы командной строки. Модуль Encode::Locale должен управлять этим.Перед тем как доступ к любым параметрам от @ARGV, сделать

use Encode::Locale; 
decode_argv(Encode::FB_CROAK); # possibly: BEGIN { decode_argv(...) } 

или использовать locale pseudoencoding, которые он обеспечивает:

my $decoded_string = decode "locale" $some_binary_data; 

Используйте это как часть в общей стратегии декодирования всех входных и всегда кодирующая свой выход ,

+0

Спасибо. Когда я пробую ваше решение, я получаю целую кучу ошибок «Malformed UTF-8 character». Теперь я предполагаю, что это связано с тем, что мой системный набор символов - ar_SA.cp1256. Нет возможности изменить набор системных символов. Должен ли я каким-то образом скрывать от ar_SA.cp1256 до utf-8 перед побегом? – user567602

+0

Ничто в моем сообщении не имеет отношения к вашему языку. Просто сохраните свои сценарии Perl как UTF-8 в своем редакторе и используйте первое решение, которое я показал. PS: Я просто подтвердил, что ваш скрипт был первоначально сохранен в CP1256 - эта кодовая страница содержит набор символов ASCII, поэтому простые скрипты Perl работают так, как ожидалось. Тем не менее, perl считает это латинским-1 и, таким образом, неверно истолковывает ваш файл. Сохранение ваших сценариев как UTF-8 - единственное портативное решение. – amon

+1

Извините, объясню немного больше, что я пытаюсь сделать. Вышеприведенное является просто тестом, но мое последнее требование заключается в том, что строка входит в качестве аргумента, когда скрипт выполняется из оболочки. Итак, я предполагаю, что если среда установлена ​​на CP1256, аргумент также будет представлен как CP1256, и мне нужно будет его преобразовать? – user567602

Смежные вопросы