Я опять поднимаю старую тему конвертации БКРС под WenLin. К своему стыду я не продвинулся ни на миллиметр. И пока что нет намерения. По этой причине я выкладываю прямо в сообщение код скрипта, с помощью которого производится преобразование файла в формате DSL в формат WenLin. Может чуть позже я добавлю комментарии к этому ужасу. Сейчас нет времени.
До сих пор программа не умеет ставить слогораздел в пиньине в словах типа 一二. К тому же WenLin плохо понимает разночтения в упрощенных/полных формах, поэтому некоторые карточки бракуются.
Я попытался пройтись скриптом по последней версии БКРС от 8 мая 2006 года. Из 150 тыс. сгенерированных статей забракованы были около 16 тыс., что не так уж и плохо.
Очень важное замечание!!!!
Так как скрипт написан на Perl5, то нормально он умеет работать только с кодировкой текста UTF8. Следовательно для правильной работы программы НЕОБХОДИМО преобразовать файл.DSL из кодировки UTF-16 в UTF-8. Затем полученный файл нужно скормить в качестве параметра скрипту. Программа выдает результаты работы на экран, поэтому их нужно перенаправить в какой-нибудь файл. Этот файл нужно ТОЖЕ преобразовать, но уже из UTF-8 в UTF-16. А затем скормить описанным на 4-ой странице способом WenLinю.
Под Linux все делается так:
[user@host:~]$ iconv -f UTF-16 -t UTF-8 <BKRS.dsl >BKRS-utf8.dsl
[user@host:~]$ ./transform.pl BKRS-utf8.dsl >wenlin-utf8.dat
[user@host:~]$ iconv -f UTF-8 -t UTF-16 <wenlin-utf8.dat >wenlin-import.dat
где transform.pl - имя нижеприведенного скрипта, а wenlin-import.dat - желаемый результат.
Под Windows честно говоря не знаю, разве что у вас есть Cygwin, где все делается аналогично.
#!/usr/bin/perl -w
use utf8;
#sub InChina {
# return <<END;
#2E00\t9FFF
#END
#}
sub partOfSpeech {
my $engname = "b.f.";
SWITCH: {
if (/сущ./) { $engname = "n.";last SWITCH;}
if (/гл./) { $engname = "v.";last SWITCH;}
if (/прил./) {$engname = "a.";last SWITCH}
}
return $engname;
}
sub makeSimple {
my($simp,$ful) = @_;
return 0 if length($simp) != length($ful);
my(@reta)=();
my @si = unpack("U*",$simp);
my @fu = unpack("U*",$ful);
for(my $i=0;$i<length($simp);$i++){
if($si[$i] == $fu[$i]) {
push @reta, ord("-");
} else {
push @reta, $fu[$i];
}
}
return pack("U*",@reta);
}
sub makeSerial {
my @nums = unpack("U*",$_);
my $ret = 0;
for(my $i=0;$i<@nums;$i++){
$ret += $nums[$i]<<(8*(@nums - $i-1));
}
return sprintf("BKRS%X",$ret&0xfffff);
}
open FILE, "<:utf8","$ARGV[0]" or die "cantopenfile";
binmode STDOUT,":utf8";
binmode STDERR,":utf8";
$lin = 0;
$newline = "\r\n";
print "cidian.db",$newline;
print $newline;
print $newline;
while(<FILE>) {
next if /^#/;
$lin++;
#Start of the ideographics entry
# while(!(/^\[/) && (/^\p{Ideographic}+/) && $_) {
my @cards = ();
while(!(/\[/) && $_) {
# print "Card = ",$_;
chomp;s/\r//;
push @cards,$_ if !/\{\{/;
$_ = <FILE>;
}
if(scalar(@cards)>0) {
# Read in radical numbering
if(s/\[m1\]\[b\]([0-9 ]+\\\[[0-9, ]+\\\])\[\/b.*/$1/) {
# print "RADICALS ",$_;
$_ = <FILE>;
}
# Skip "instead of..."
if (/\[m1\]\[b\]\\\[\[\/b\]/) {
# print "skipping instead of....";
$_ = <FILE>;
}
my $pinyin = "";
# Let's read out pinyin
if(s/\[m1\]\[b\](\p{Latin}+)([,;] \p{Latin}+)?\[\/b.*/$1/) {
chomp;
$pinyin = $_;
}
next if $pinyin eq "";
print $newline,"*** $lin ***",$newline;
print "pinyin ",$pinyin,"$newline";
print "characters ",$cards[0];
if(scalar(@cards) > 1) {
# print "len = ",length($cards[0]);
my $ms = makeSimple(@cards);
# $ms = makeSimple(@cards[1]) if !$ms;
print "[",$ms,"]" if $ms;
}
print $newline;
print "serial-number ",makeSerial($cards[0]),
int($lin%100000),$newline;
my $curpos = 0;
$pofspe = 0;
$curpos = tell FILE;
$_ = <FILE>;
POFSPE:
if(/\[m1\]\[b\][IVX]+.*/) {
# Different parts of speech
$pofspe++;
if (/\[c\] *\[i\](.+)\[\/i\] *\[\/c\]\[\/m\]/) {
print $pofspe,"part-of-speech ",partOfSpeech($1),$newline;
}
$curpos = tell FILE;
$_ = <FILE>;
# print $pofspe,"part-of-speech b.f.$newline";
}
if (/\[m2\]\[c\] *\[i\](.+)\[\/i\] *\[\/c\]\[\/m\]/) {
print "part-of-speech ",partOfSpeech($1),$newline;
$curpos = tell FILE;
$_ = <FILE>;
} else {
print "part-of-speech b.f.$newline" if ($pofspe == 0);
}
if(!/\[m2\]/) {
print "definition simplified",$newline
} else {
while (/\[m2\]/) {
my $defnum = 0;
$defnum = $1 if(s/\[m2\]([0-9]+)(\)|\.)//);
my $def = "";
my $flag;
s/\[[icm0-9\/]+\]//g;
s/\\//g;
chomp;
s/\r//;
if ($pofspe == 0) {
print "definition " if $defnum == 0;
} else {
print $pofspe,"definition " if $defnum == 0;
}
print $defnum+$pofspe*10,"definition " if $defnum>0;
print $_,$newline;
$curpos = tell(FILE);
$_ = <FILE>;
my (@exms,@trans)=((),());
while (/\[m4\]/) {
my $example;
my $transl;
/\p{Ideographic}+(\P{Ideographic}+)\[\/ex\]/;
$transl = $1;
# print "LINE: $_" if(not defined $transl);
$transl =~ s/\[[icm0-9\/]+\]//g if defined $transl;
/\[ex\]((\p{Ideographic}|\\| |\pP|\p{Latin})+)/;
$example = $1;
$example =~ s/\[[icm0-9\/]+\]//g if defined $example;
if (defined($example) && defined ($transl)) {
push @exms,$example;
push @trans,$transl;
}
$curpos = tell FILE;
$_ = <FILE>;
}
my $globnum = $pofspe;
$globnum = $defnum+$globnum*10 if $defnum>0;
$globnum = $globnum*10+1 if @exms>1;
for (my $i=0;$i<@exms;$i++) {
print $globnum+$i if $globnum >0;
print "example ",$exms[$i],$newline;
print $globnum+$i if $globnum >0;
print "translation ",$trans[$i],$newline;
}
}
}
goto POFSPE if(/\[m1\]\[b\][IVX]+/);
seek(FILE,$curpos,0) if($curpos != 0);
} else {
# print "Error!!!! $_ \r\n";
}
# last if $lin>90840;
# last if $lin>90050;
}