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 を使用しました。