Perl日语到英文文件名替换

时间:2013-06-11 08:58:25

标签: regex perl encoding utf-8

我整理了一个perl脚本,用于将日文文件名替换为英文文件名。但仍有一些我不太了解的事情。

我有以下配置 客户端操作系统:

Windows XP Japan

Notepad ++,已安装

服务器:

红帽企业Linux服务器版本6.2

Perl v5.10.1

VIM:VIM版本7.2.411

Xterm:ASTEC-X版本6.0

CSH:tcsh 6.17.00(Astron)

文件的来源是在Windows上生成的日文.csv文件。我看到有关在Perl中使用utf8和编码转换的帖子,我希望更好地理解为什么我不需要在其他线程中提到的任何内容。

这是我的脚本有效吗?我的问题如下。

#!/usr/bin/perl
my $work_dir = "/nas1_home4/fsomeguy/someplace";
opendir(DIR, $work_dir) or die "Cannot open directory";
my @files = readdir(DIR);
foreach (@files) 
{
    my $original_file = $_; 
    s/機/–machine_/; # replace 機 with -machine_
    my $new_file = $_;
    if ($new_file ne $original_file)
    {
        print "Rename " . $original_file . " to " . $new_file;
        rename("${work_dir}/${original_file}", "${work_dir}/${new_file}") or  print "Warning: rename failed because: $!\n";
    }
}

问题:

1)为什么这个样本不需要utf8?我需要什么类型的例子。 使用uft8;讨论过:use utf8 gives me 'Wide character in print')?但是如果我添加了使用utf8,那么这个脚本将不起作用。

2)为什么此样本中不需要编码操作?
我实际上是使用Notepad ++在Windows中编写脚本(将日文字符从Windows XP Japan的资源管理器粘贴到我的脚本中)。在Xterm和VIM中,字符显示为垃圾字符。但我也没有处理编码操作,这在这里讨论How can I convert japanese characters to unicode in Perl?

感谢。

更新1

在Perl中测试一个简单的本地化示例,用于替换日语中的文件名和文件文本

在Windows XP中,从.csv数据文件中复制南字符并复制到剪贴板,然后将其用作文件名(即南.txt)和文件内容(南)。在Notepad ++中,在UTF-8编码下读取文件显示x93xEC,在SHIFT_JIS下读取它显示南。

脚本:

使用以下Perl脚本south.pl,它将在具有Perl 5.10的Linux服务器上运行

#!/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)取消评估选项1和3,(评论选项2和4) 设置:Readdir编码,SHIFT_JIS;文件打开编码SHIFT_JIS 结果:文件名替换失败.. 错误:utf8&#34; \ x93&#34;没有映射到.//south.pl第68行的Unicode。 \ X93

(BAD)取消评估选项2和4(评论选项1和3) 设置:Readdir编码,utf8;文件打开编码utf8 结果:文件名替换工作,生成了south.txt 但是south1.txt文件内容替换失败,它有内容\ x93()。 错误:&#34; \ x {fffd}&#34;没有映射到shiftjis at .//south.pl第25行。 ...... -Ao?=(Bx {fffd} .txt

(GOOD)取消评估选项2和3,(评论选项1和4) 设置:Readdir编码,utf8;文件打开编码SHIFT_JIS 结果:文件名替换工作,生成了south.txt South1.txt文件内容替换有效,它有内容南。

结论:

我必须使用不同的编码方案才能正常工作。 Readdir utf8和文件处理SHIFT_JIS,因为csv文件的内容是SHIFT_JIS编码的。

1 个答案:

答案 0 :(得分:2)

你的脚本完全不知道unicode。它将所有字符串视为字节序列。幸运的是,编码文件名的字节与编码源中使用的日文字符的字节相同。如果告诉Perl use utf8,它会解释脚本中的日文字符,但不会解释来自文件系统的日文字符,因此不会匹配。