NasupiiのPerl書抜帳
特許文献用の符号表作成支援プログラムソースコード
ソースコード
#####################################################################################################
# extract_marks.pl ver2.0
#
# このプログラムは UTF-8 で記述すること。他の文字コードで記述すると文字化けする。
#
# 特許公報から、符号を抽出し、csvファイルとして書き出す
# Copyright (C) Nasupii
#
# 2011/01/08 初版作成 (Shift-JIS専用)
# 2014/09/21 一部修正した (Ver 1.1)
# 符号に中点を追加した。第+数字を符号から除外した。
# 出力ファイル名を 符号表.csv に変えた
# 番号の最後のほうが抽出されないバグを修正した
# 2024/01/08 UTF-8に対応した。入力ファイルは Shift-JIS と UTF-8 を自動判定し、
# 出力ファイルは、Shift-JIS の csv ファイルとした。 (Ver.2.0)
#####################################################################################################
# 動作確認環境
# Strawberry Perl 5.36.1.1 がインストールされた Windows 10 にて動作確認した。
# Perl ver.5.10 以降なら、Encode が標準ライブラリーに加えられているので、たぶん動作するでしょう。
# Windows の他のバージョンでもたぶん動作するでしょう。
# 使用方法
# J-PlatPat等から入手した公報のテキストデータを、 "infile.txt" としてファイルする。
# このプログラムを "infile.txt" があるフォルダにコピーし、ダブルクリックする。
# 符号及び符号の前後の文字列が抽出され、"符号表.csv" として カレントフォルダに書き出される。
# MS-Excel等の表計算ソフトで "符号表.csv" を読み込むと、符号の一覧表が得られる。
# 注意事項
# このソフトは構文解析を行っているわけではないので、符号ではないものまで抽出されたり、
# 同じ符号が複数回抽出されたりしているので、符号の前後の文字列を見ながら手作業での修正が必要です。
# しかし、公報の全文からすべて手作業で符号を抽出するよりは、大幅な時間短縮が出来ます。
# 符号の判別法は、数字、アルファベット大文字小文字、’”,・だけからなる文字列を符合としています
# 上記以外の文字列が符号として使用されている場合は、抽出できない場合があります。
#####################################################################################################
use strict;
use warnings;
use utf8;
use Encode qw/decode encode/;
use Encode::Guess;
binmode STDIN, ':encoding(cp932)';
binmode STDOUT, ':encoding(cp932)';
binmode STDERR, ':encoding(cp932)';
my $fname_in = "infile.txt";
my $fname_out = encode("cp932", "符号表.csv"); # 漢字のファイル名を Shift-JIS(cp932) コードに変換
my ($nn, $an, $mk, $buf, $i, $j, $line, @lines, $enc);
my ($pre, $post, $mark, $mark1, $mark2, @marks, @marksx);
$nn = "0|1|2|3|4|5|6|7|8|9";
$an = $nn . "|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z";
$an .= "|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z";
$mk = $an . "|’|”|,|・"; #Ver1.1 中点を追加
#####################################################################################################
# step0 読み込み、コード判定、コード変換
#####################################################################################################
$buf = "";
if(! open(IN, "<", $fname_in)) { # 入力ファイルを開く
print "$fname_in が開けなかったので実行が中断されました。\n";
exit;
}
while($line = <IN>) { # 入力ファイルを読み込む
$buf .= $line;
}
close(IN); # 入力ファイルを閉じる
$enc = guess_encoding($buf, qw/cp932 utf8/); # 文字コードを判定する
if(! ref($enc) ){ # エラートラップ
print "文字コードが判定できなかったので実行が中断されました。\n";
exit;
}
#print "文字コードを ", $enc->name, " と判定しました。\n";
$buf = decode($enc->name, $buf); # 読み込んだファイルをperlの内部表現に変換する
#####################################################################################################
# step1 半角文字を削除
#####################################################################################################
$buf =~ s/[ a-zA-Z0-9\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~]//gm;
#####################################################################################################
# step2 "【"から始まる行を空行に変える
#####################################################################################################
$buf =~ s/^【.+?$//gm;
#####################################################################################################
# step3 句読点の後ろに改行を入れる
#####################################################################################################
$buf =~ s/、/、\n/gm;
$buf =~ s/。/。\n/gm;
#####################################################################################################
# step4 符号から除外する数字を削除し、改行に置き換える
# "請求項"+数字 "図"+数字 "文献"+数字 数字+"の実施形態" 数字+"の実施例" 数字+"の発明"
#####################################################################################################
$buf =~ s/(請求項|図|文献)($nn)+/\n/gm;
$buf =~ s/($nn)+(の実施形態|実施形態|の実施例|実施例|の発明|発明)/\n/gm;
#####################################################################################################
# step5 一行ずつの配列に分ける。
#####################################################################################################
@lines = split(/\n/, $buf);
#####################################################################################################
# step6 符号を含まない行を空行に変える
#####################################################################################################
foreach $line (@lines) {
if($line !~ m/($mk)/) {
$line = "";
}
}
#####################################################################################################
# step7 空行を削除
#####################################################################################################
@lines = grep(/./, @lines);
#####################################################################################################
# step8 符号部の前に"="、後にタブを挿入
#####################################################################################################
foreach $line (@lines) {
$line =~ s/((?:$mk)+)/=$1\t/g;
}
#####################################################################################################
# step9 行頭から始まる符号を削除
#####################################################################################################
foreach $line (@lines) {
$line =~ s/^=($mk)+\t//g;
}
#####################################################################################################
# step10 第+数字を符号から除外する Ver1.1
#####################################################################################################
foreach $line (@lines) {
$line =~ s/第=((?:$nn)+)\t/第$1/g;
}
#####################################################################################################
# step11 符号の前後を取り出し配列に入れる
#####################################################################################################
@marks = (); # @marks を初期化
foreach $line (@lines) {
$line = "\t" . $line . "=";
while($line =~ s/\t(.*?)=(.*?)\t(.+?)=/\t$3=/) {
push(@marks, join("\t", $2, $1, $3));
}
}
#####################################################################################################
# step12 数字の桁数をそろえる(3桁と仮定する)
#####################################################################################################
foreach $line (@marks) {
($mark, $pre, $post) = split(/\t/, $line);
if($mark =~ m/^($nn){3}/) {
}elsif($mark =~ m/^($nn){2}/) {
$mark = " " . $mark;
$line = join("\t", $mark, $pre, $post);
}elsif($mark =~ m/^($nn)/) {
$mark = " " . $mark;
$line = join("\t", $mark, $pre, $post);
}
}
#####################################################################################################
# step13 符号の前の文字を逆順に並べる
#####################################################################################################
foreach $line (@marks) {
($mark, $pre, $post) = split(/\t/, $line);
$pre = reverse($pre);
$line = join("\t", $mark, $pre, $post);
}
#####################################################################################################
# step14 並べ替え
#####################################################################################################
@marks = sort(@marks);
#####################################################################################################
# step15 符号及び符号の前が同一のものを一つにまとめる
# 同じ符号で符号の前に同じ文字列がある場合は、一番短いものにまとめる
#####################################################################################################
$i = 0;
$j = 1;
@marksx = ();
do {
($mark, $pre, $post) = split(/\t/, $marks[$i]);
$mark1 = join("\t", $mark,$pre);
($mark, $pre, $post) = split(/\t/, $marks[$j]);
$mark2 = join("\t", $mark,$pre);
if($mark1 eq $mark2) {
$j++;
}elsif((length($mark1) < length($mark2)) and ($mark1 eq substr($mark2,0,length($mark1)))) {
$j++;
}else{
push(@marksx, $marks[$i]);
$i = $j;
$j++;
}
}while ($j<=$#marks);
push(@marksx, $marks[$i]);
#####################################################################################################
# step16 符号の前の文字列を逆順から元に戻す
#####################################################################################################
foreach $line (@marksx) {
($mark, $pre, $post) = split(/\t/, $line);
$pre = reverse($pre);
$line = join("\t", $mark, $pre, $post);
}
#####################################################################################################
# step17 ファイル書き出し
#####################################################################################################
if(! open(OUT, ">:encoding(cp932)", $fname_out)) { # ファイルを開く
print "$fname_out が開けなかったので実行が中断されました。\n";
exit;
}
print OUT qq("","符号表"\n\n);
foreach $line (@marksx) {
($mark, $pre, $post) = split(/\t/, $line);
print OUT qq("$pre","[$mark]","$post"\n);
}
close(OUT); # ファイルを閉じる
exit;
Copyright (C) Nasupii