0

Windows から SHIFT_JIS (日本語) でエンコードされた csv ファイルのセットがあり、Perl v5.10.1 を実行している Linux サーバーで正規表現を使用して文字列を置換しようとしています。

これが私の要件です。Perl スクリプトの正規表現を人間が読める形式 (少なくとも日本人にとっては) にしたいのです。このように: s/北/0/g; 代わりに、いくつかの 16 進コード s/\x{4eba}/0/g; が散らばっています。

現在、Windows の Notepad++ で Perl スクリプトを編集しており、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;

これにより、csv ファイルの 10:00 が 9:00 に正常に置き換えられますが、上部に utf8 が含まれていない限り、北 (つまり北) を 0 に置き換えることができませんでした。

質問:

1) オープン ドキュメントhttp://perldoc.perl.org/functions/open.htmlでは、暗黙的でない限り、utf8 を要件として使用していませんか?

a) utf8 のみを使用した場合、ループ内の最初の print ステートメントで、xterm 画面に文字化けが出力されます。

b) :encoding(shift_jis) のみで open を呼び出した場合、ループ内の最初の print ステートメントで日本語の文字が xterm 画面に出力されますが、置換は行われません。use utf8 が指定されていないという警告はありません。

c) a) と b) の両方を使用した場合、この例は機能します。

「use utf8」は、この Perl スクリプトで :enoding(shift_jis) を使用して open を呼び出す動作をどのように変更しますか?

2)エンコーディングを指定せずにファイルを開こうとしましたが、Perlはファイル文字列を生のバイトとして扱いませんでした。スクリプトに貼り付けた文字列が同じエンコーディングである場合、正規表現の一致をそのように実行できませんでした。元のデータ ファイルのテキストとして? エンコーディングをまったく指定せずに、この方法で以前にファイル名の置換を行うことができました (ここで私の関連記事を参照してください: Perl Japanese to English filename replacement )。

ありがとう。

アップデート 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; file open encoding SHIFT_JIS 結果: ファイル名の置換に失敗しました.. エラー: utf8 "\x93" は .//south.pl 行 68 の Unicode にマップされません。\x93

(悪い) オプション 2 と 4 のコメントを外します (オプション 1 と 3 のコメント) セットアップ: Readdir エンコーディング、utf8; file open encoding utf8 結果: ファイル名の置換が機能し、south.txt が生成されましたが、south1.txt ファイルの内容の置換に失敗しました。内容は \x93 () です。エラー: "\x{fffd}" は .//south.pl 行 25 の shiftjis にマップされません。 ... -Ao?= (Bx{fffd}.txt

(GOOD) オプション 2 と 3 のコメントを外します。(オプション 1 と 4 のコメントを付けます) セットアップ: Readdir エンコーディング、utf8; file open encoding SHIFT_JIS 結果: ファイル名の置換が機能し、south.txt が生成されました South1.txt ファイルのコンテンツの置換が機能し、コンテンツは south になりました。

結論:

この例を正しく動作させるには、別のエンコード スキームを使用する必要がありました。csv ファイルの内容が SHIFT_JIS でエンコードされていたため、readdir utf8 とファイル処理 SHIFT_JIS を使用しました。

4

1 に答える 1

1

開始するには、utf8 モジュールのドキュメントを読むことをお勧めします。それは言う:

use utf8プラグマは、Perl パーサーに、現在のレキシカル スコープのプログラム テキストで UTF-8 を許可するように指示します (EBCDIC ベースのプラットフォームでは UTF-EBCDIC を許可します) 。プラグマは、現在のno utf8レキシカル スコープでソース テキストをリテラル バイトとして扱うように切り替えるように Perl に指示します。

コードに含まれていない場合use utf8、Perl コンパイラは、ソース コードがシステムのネイティブ 1 バイト エンコーディングであると想定します。また、「北」という文字はほとんど意味がありません。プラグマを追加すると、コードに Unicode 文字が含まれていることを Perl に伝え、すべてが機能し始めます。

于 2013-06-12T16:01:23.190 に答える