読者です 読者をやめる 読者になる 読者になる

テキストファイルの中からCJK互換漢字をあぶり出す

文字コード Perl Cygwin

先日、メモ帳のテキストにおかしな漢字(CJK互換漢字)があるという感じの記事を書きましたが、そんな漢字をあぶり出すスクリプトを考えましたので今回はその紹介。

tuttitan.hatenablog.com

 

スクリプトPerlで作られており、内容としてはテキストファイルを開いて1文ずつ文字コードを調査していき、コード的にU+F900~U+FF00の文字があったら表示するというものです。

CygwinPerl環境で動作確認していますが、環境が変わると文字が化けたり正しいコードが取れない可能性があるので参考にする場合はご注意下さい。

文字コード関連でのはまりどころとしては、STDOUTをutf8に設定するところと、テキストファイルをopenするところでutf8を指定するところでしょうか。なお、テキストファイルはutf8(BOMなし)改行(LF)でエンコードされている前提です。

 

ちょいと汚いですが、以下がコードになります。

#!/usr/bin/perl

use strict;
use warnings;

# エンコードの設定
use utf8;
binmode(STDOUT, ":utf8");
binmode(STDERR, ":utf8");

# 文字色の設定
use Term::ANSIColor qw(:constants);
$Term::ANSIColor::AUTORESET = 1;

print "Script Start...\n";

if (0 != $#ARGV) {
    die "開くファイルを引数で指定して下さい";
}

unless (-e $ARGV[0]) {
    die "$ARGV[0]は存在しません";
}

my $file = $ARGV[0];  # ファイル名
our $cntFind = 0;


open(FDI, "<:utf8", "$file");

my $content;  # ファイルの全内容

# 一時的に入力セパレータを無効して$contentにすべて読み込む
{
    local $/ = undef;
    $content = <FDI>;
}

my $cntLine = 1;
my $column  = 1;

my @chars = split(//, $content);
my $compatiCode1 = 63744;  # 0xF900
my $compatiCode2 = 65280;  # 0xFF00

for (my $x = 0; $#chars >= $x; ++$x) {

    my $code = ord($chars[$x]);

    # CJK互換文字を見つけたら表示する
    if (($code >= $compatiCode1) &&($code < $compatiCode2)) {
        print BOLD RED "NG";
        printf("  line: %4d | col: %3d | char: %s(0x%x)\n", $cntLine, $column, $chars[$x], $code);
        ++$cntFind;
    }

    ++$column;  # 1文字処理したのでカラムを+1する

    # 行末の処理
    if ($chars[$x] =~ /\n/) {
        $column  = 1;
        ++$cntLine;
    }
}
close(FDI);

print "\n";
print "=============================\n";
print "見つかった数: $cntFind\n";
print "=============================\n";
print "\n";

print "...Script End\n";