我参与了数字无线电传播研究,其中远程发射机在定义的时间发送预定义的信标,该信标很容易与正则表达式匹配。
但是由于太阳和大气条件,它并不总是100%解码。我想要做的是计算解码的百分比。
信标格式如下:
de va6shs va6shs va6shs Loc DO46gs Olivia-4-250 NBEMS test 2218Z
| | | |
(Station) (Location) (Digital Mode) (UTC Time)
我可以用Perl实际计算百分比,还是应该寻找其他解决方案?
编辑:由于在我们使用的数据模式中纠错有限,经常会发生这种情况,因此随机字符通常最终出现在已解码的字符串中,或者字符不会解码所有这些都是在不同时间从同一台接收到的字符串在太阳能条件恶化的同一天。
100% decode
de ve6rfm ve6rfm ve6rfm Loc DO46gs Olivia-4-250 NBEMS test 0218Z
93.75%
P!de ve6rfm ve6rfm ve6rfm Loc DO46gs Olivia-4-250 NBEMS <TAB>est F248Z
9.375%
de ve6rfmr&
两个信标字符串之间唯一的区别是字符串末尾的UTC时间,但正如您所看到的那样,有几个字符没有正确解码。
正确解码字符串有64个字符。 第一个错误解码的字符串有60个正确的字符。 所以60/64 * 100 = 93.75%解码。
我的电台呼号的正则表达式,三个重复的单词是
/[vV][aAeEyY][15678]\w{2,3}/
这项研究涉及加拿大西部的几个不同的站点,因此我需要将它们作为传播许可证使用,并且使用上述正则表达式使我不必每次新电台播出时都必须更新我的脚本。
答案 0 :(得分:2)
您可以计算与初始字符串的长度相匹配的字符数,例如查找/\bva\dshs\b/
(\b
是字边界和{{ 1}}是数字,请参阅the manual page)
\d
匹配的字符串,组合,给出
my $s = 'de va6shs va6shs va6shs Loc DO46gs Olivia-4-250 NBEMS test 2218Z';
my $r = join('', $s =~ m/\bva\dshs\b/g);
print(((length($r)*100) / length($s)) . "%\n");
是 28.125%的初始字符串长度。
答案 1 :(得分:1)
问题是部分或模糊匹配之一。有些模块可能有所帮助。他们大多使用 Levenshtein距离,即从另一个获得一个字符串所需的编辑次数,但还有其他方法。查看Text::Levenshtein中的部分列表。有关提供更多内容的搜索词组,请参阅this post。
以下是使用String::Approx,String::Similarity和Text::Fuzzy的示例。 None没有给出你所要求的内容,但都会检索类似的度量,并且有可以让你获得目标的选项。
value = float(value) if value != '--undefined--' else 0
请查看他们的文档。
use warnings 'all';
use strict;
my $beacon =
'de va6shs va6shs va6shs Loc DO46gs Olivia-4-250 NBEMS test 2218Z';
my $received =
'P!de ve6rfm ve6rfm ve6rfm Loc DO46gs Olivia-4-250 NBEMS <TAB>est F248Z';
# Can use an object, or the functional interface
use Text::Fuzzy qw(fuzzy_index distance_edits);
my $tf = Text::Fuzzy->new ($beacon);
my ($offset, $edits, $distance);
# Different distance/edits
$distance = $tf->distance($received);
($offset, $edits, $distance) = fuzzy_index ($received, $beacon);
($distance, $edits) = distance_edits ($received, $beacon);
# Provides "similarity", in terms of edit distance
use String::Similarity;
my $similarity = similarity $beacon, $received;
# Can be tuned, but is more like regex in some sense. See docs.
use String::Approx qw(amatch);
my @matches = amatch($beacon, $received); # within 10%
# amatch($beacon, ["20%"], $received); # within 20%
# amatch($beacon, ["S0"], $received); # no "substitutions"
考虑&#34;匹配&#34;如果长度不超过10%。这是默认设置,模块允许调整该参数。例如,
String::Approx
将达到20%。可以为您提供其他可能的改进。 较新版本的模块是用C语言编写的,效果要好得多。