====== 植物拉丁名校验species_la-verify.pl ======
===== 拉丁名 =====
植物物种采用拉丁文的双名命名法,通常都很长。手工输入难免出错,一般都是错误一两个字母的情形,肉眼很难发现。如果我们有一个事先校验过的名录,只需将输入的拉丁名与名录中的名字做个相似性比较,就很容易发现并纠正此类小错误,从而可以避免后续分析处理时可能导致巨大误差的潜在风险。
这里说的物种拉丁名,指拉丁名通用代码,不包含命名人等部分,通常由属名和种加词构成,如果是变种、亚种等,则包括相应的变种加词、亚种加词等。如:
* Abelia macrotera
* Abelmoschus manihot var. manihot
* Acer caesium subsp. giraldii
* Angelica decursiva form. albiflora
===== 程序功能 =====
程序流程:
- 将拉丁名与名录对照,如果命中,则认为拉丁名是正确的,输出该拉丁名,以及标志“FINE”;
- 如果找不到,则在名录中进行相似性搜索,找出与该拉丁名相似率在90%以上的所有名称,与该拉丁名一起列出,供用户选择,缺省为该拉丁名:
* 如果用户仍旧选择该拉丁名,则输出名称和标志“NEW”;
* 如果用户选择了名录中的名称,则输出名称和标志“MOD”。
- 如果相似搜索失败,则直接输出名称和标志“NEW”。
这里对不同的结果设置了一些标志,供后续处理。比如标志为“NEW“的名称,如果确认无误,则可以将其添加到名录里,这样名录会不断增长,可用性和准确性也随之提高。
===== String::Similarity模块 =====
相似性比较用到String::Similarity模块,需要事先安装,详细信息可访问[[http://search.cpan.org/~mlehmann/String-Similarity-1.04/Similarity.pm|CPAN]]。
如果系统是[[http://www.centos.org|CentOS]],并且启用了[[http://repoforge.org|RPMforge]]源,则可以直接YUM安装:
yum install perl-String-Similarity
如果从源代码安装,方法如下:
gunzip String-Similarity-1.04.tar.gz
tar xvf String-Similarity-1.04.tar
cd String-Similarity-1.04/
perl Makefile.PL
make
make test
make install
===== 代码简述 =====
使用String::Similarity模块:
use String::Similarity;
参数分别为名录文件和要校验的名称列表文件:
my $conf_file = shift;
my $la_file = shift;
读入名录,放到列表变量里:
my @conf;
open(IN, $conf_file);
chomp(@conf = );
close IN;
读入要校验的名称列表,同时放到列表变量和哈希变量里,这样的相同的名字都对应同一个哈希键(key),避免后续的重复校验:
my @all_list;
my %la_names;
open(IN, $la_file);
while () {
chomp;
push @all_list, $_;
$la_names{$_} = "";
}
close IN;
对每个哈希键(拉丁名称)依次进行处理。如果键为空,则设定标志“NONE”:
foreach my $value (keys %la_names) {
if ($value eq "") {
$la_names{$value} = "NONE\t" . $value;
next;
}
如果键存在于名录中,则设定标志“FINE”:
my @temp_list = grep { $_ eq $value } @conf;
if (@temp_list) {
$la_names{$value} = "FINE\t" . $value;
next;
}
进行相似性搜索:
@temp_list = grep { similarity($_, $value, 0.9) >= 0.9 } @conf;
如果搜不到,则直接设定标志“NEW”:
if (!@temp_list) {
$la_names{$value} = "NEW\t" . $value;
next;
}
列出所有结果供用户选择:
my $choose;
print STDERR "[$value] Similar Records:\n";
print STDERR "0): $value\n";
my $i = 1;
foreach (@temp_list) {
print STDERR "$i): $_\n";
$i++;
}
while (1) {
print STDERR "Please choose(Ctrl+C to Abort)[0]: ";
chomp($choose = );
last if ($choose >= 0 && $choose <= @temp_list);
}
根据选择结果设定相应标志:
if ($choose) {
$la_names{$value} = "MOD\t" . $temp_list[$choose - 1];
} else {
$la_names{$value} = "NEW\t" . $value;
}
处理完所有键后,根据哈希中的设置输出所有名称的校验结果:
foreach (@all_list) {
print STDOUT $la_names{$_} . "\r\n";
}
exit 0;
完毕。
{{tag>Perl}}