2013-06-12 6 views
0

У меня есть набор файлов SHST_JIS (японского) csv из Windows, который я пытаюсь обработать на Linux-сервере под управлением Perl v5.10.1 с использованием регулярных выражений для замены строк.Обработка файлов Perl на SHIFT_JIS закодированных японских файлах

Это мое требование: Я хочу, чтобы регулярные выражения скрипта Perl были понятными для человека (по крайней мере, для японского человека) Т.е. например: s/北/0/g; Вместо него усеяны шестым кодом s/\ x {4eba}/0/g;

Сейчас я редактирую скрипт Perl в Notepad ++ в Windows и вставляя строку, которую мне нужно найти из файла данных csv на скрипт Perl.

У меня есть следующий рабочий сценарий тестирования ниже:

use strict; 
use warnings; 
use utf8; 

open (IN1, "<:encoding(shift_jis)", "${work_dir}/tmp00.csv") or die "Error: tmp00.csv\n"; 
open (OUT1, "+>:encoding(shift_jis)" , "${work_dir}/tmp01.csv") or die "Error: tmp01.csv\n"; 

while (<IN1>) 
{ 
    print $_ . "\n"; 
    chomp; 
    s/北/0/g; 
    s/10:00/9:00/g;  
    print OUT1 "$_\n"; 
}  

close IN1; 
close OUT1; 

Это успешно заменить 10:00 с 9:00 в .csv файл, но вопрос я не смог заменить 北 (то есть. North) с 0, если не использовать utf8 также в верхней части.

Вопросы:

1) В открытой документации, http://perldoc.perl.org/functions/open.html, я не видел использовать utf8 как требование, если оно не подразумевается?

a) Если бы я использовал utf8 только, то первый оператор печати в цикле печатает символ мусора на моем экране xterm.

b) Если бы я открывал только с: encoding (shift_jis), то первый оператор печати в цикле печатал японский символ на моем экране xterm, но замены не было бы. Существует никаких предупреждений о том, что использование utf8 не указано.

c) Если я использовал оба a) и b), то этот пример работает.

Как «использовать utf8» изменить поведение вызова open с помощью: enoding (shift_jis) в этом скрипте Perl?

2) Я также попытался открыть файл без какой-либо кодировки, не будет ли Perl обрабатывать строки файла как необработанные байты и иметь возможность выполнять регулярное выражение таким образом, если строки, вставленные в скрипт, являются в той же кодировке, что и текст в исходном файле данных? Ранее я смог выполнить замену имени файла без указания какой-либо кодировки (см. Мой связанный пост здесь: Perl Japanese to English filename replacement).

Спасибо.

ОБНОВЛЕНИЕ 1

Тестирования простой локализации образец в Perl для имени файла и файл замены текста на японском языке

В Windows XP, скопируйте 南 символ из файла в формате CSV данных и скопируйте в буфер обмена, затем используйте его как имя файла (то есть. 南 .txt), так и содержимое файла (南). В Notepad ++ чтение файла под кодировкой UTF-8 показывает x93xEC, его чтение под SHIFT_JIS отображает 南.

Сценарий:

Используйте следующий Perl south.pl скрипт, который будет выполняться на сервере Linux с Perl 5,10

#!/usr/bin/perl 
use feature qw(say); 

use strict; 
use warnings; 
use utf8; 
use Encode qw(decode encode); 

my $user_dir="/usr/frank"; 
my $work_dir = "${user_dir}/test_south"; 

# forward declare the function prototypes 
sub fileProcess; 

opendir(DIR, ${work_dir}) or die "Cannot open directory " . ${work_dir}; 

# readdir OPTION 1 - shift_jis 
#my @files = map { Encode::decode("shift_jis", $_); } readdir DIR; # Note filename could not be decoded as shift_jis 
#binmode(STDOUT,":encoding(shift_jis)");      

# readdir OPTION 2 - utf8 
my @files = map { Encode::decode("utf8", $_); } readdir DIR; # Note filename could be decoded as utf8 
binmode(STDOUT,":encoding(utf8)");       # setting display to output utf8 

say @files;         

# pass an array reference of files that will be modified 
fileNameTranslate(); 
fileProcess(); 

closedir(DIR); 

exit; 

sub fileNameTranslate 
{ 

    foreach (@files) 
    { 
     my $original_file = $_; 
     #print "original_file: " . "$original_file" . "\n";  
     s/南/south/;  

     my $new_file = $_; 
     # print "new_file: " . "$_" . "\n"; 

     if ($new_file ne $original_file) 
     { 
      print "Rename " . $original_file . " to \n\t" . $new_file . "\n"; 
      rename("${work_dir}/${original_file}", "${work_dir}/${new_file}") or print "Warning: rename failed because: $!\n"; 
     } 
    } 
} 

sub fileProcess 
{ 

    # file process OPTION 3, open file as shift_jis, the search and replace would work 
    # open (IN1, "<:encoding(shift_jis)", "${work_dir}/south.txt") or die "Error: south.txt\n"; 
    # open (OUT1, "+>:encoding(shift_jis)" , "${work_dir}/south1.txt") or die "Error: south1.txt\n"; 

    # file process OPTION 4, open file as utf8, the search and replace would not work 
open (IN1, "<:encoding(utf8)", "${work_dir}/south.txt") or die "Error: south.txt\n"; 
    open (OUT1, "+>:encoding(utf8)" , "${work_dir}/south1.txt") or die "Error: south1.txt\n"; 

    while (<IN1>) 
    { 
     print $_ . "\n"; 
     chomp; 

     s/南/south/g; 


     print OUT1 "$_\n"; 
    } 

    close IN1; 
    close OUT1; 
} 

Результат:

(BAD) Uncomment Варианты 1 и 3, (Комментарий Вариант 2 и 4) Настройка: кодировка Readdir, SHIFT_JIS; файл открыт кодирование SHIFT_JIS Результат: файл замена имя не удалось .. Ошибка: utf8 "\ x93" не отображает в Unicode в .//south.pl линии 68. \ x93

(БАД) Раскоментируйте Вариант 2 и 4 (Комментарий Вариант 1 и 3) Настройка: кодировка Readdir, utf8; file open encoding utf8 Результат: смена имени файла сработала, сгенерирован файл south.txt Но сбой в замене содержимого файла south1.txt, он имеет содержимое \ x93(). Ошибка: "\ х {FFFD}" не отображает в shiftjis на .//south.pl линии 25. ... -ao = (Bx {FFFD} .txt

(ХОРОШО) Раскоментируйте Вариант 2 и 3, (Комментарий Вариант 1 и 4) Настройка: кодировка Readdir, utf8; открытая кодировка файла SHIFT_JIS Результат: смена имени файла сработала, сгенерирован сгенерированный south.txt Работа с содержимым файла содержимого South1.txt, содержание юга на нем.

Вывод:

мне пришлось использовать другую схему кодирования для этого примера, чтобы работать р roperly. Readdir utf8 и обработки файлов SHIFT_JIS, поскольку содержимое файла csv кодировалось SHIFT_JIS.

ответ

1

Хорошим местом для начала было бы читать the documentation for the utf8 module. Который говорит:

The use utf8 pragma tells the Perl parser to allow UTF-8 in the program text in the current lexical scope (allow UTF-EBCDIC on EBCDIC based platforms). The no utf8 pragma tells Perl to switch back to treating the source text as literal bytes in the current lexical scope.

Если у вас нет use utf8 в коде, то компилятор Perl предполагает, что ваш исходный код в родной кодировке однобайтной вашей системы. И персонаж «北» будет иметь мало смысла. Добавление прагмы говорит Perl, что ваш код включает символы Unicode, и все начинает работать.

+0

Спасибо Дэйв, вы могли бы объяснить разницу между UTF-8 и SHIFT_JIS? UTF8 - это схема кодирования, поэтому моя путаница в том, что если SHIFT_JIS также является (другой) схемой кодирования, тогда, когда я использую прагму utf8, тогда мой исходный скрипт (который содержит SHIFT_JIS) не будет интерпретироваться как один байт, но как utf8 символов. Затем я вызываю open с: encoding (SHIFT_JIS), символы из файла будут символами SHIFT_JIS. Если две схемы кодирования не равны, я не вижу, как это будет работать. Я не мог сказать, так ли это на странице wikiipedia SHIFT_JIS. – frank

+0

Я обновил пример, который иллюстрирует другую схему кодирования, которую я использовал, чтобы заменить замену имени файла и замены файла. – frank

+0

Кодирование имен файлов определяется операционной системой. Вы не можете это изменить. Кодирование содержимого файла определяется человеком, который пишет файл. –