我正在研究字形模块,我必须构建正则表达式,该表达式可以找到与ASCII等效项相对应的字形文本。
因此,例如,我的性格没有同形异义字:
my $f = 'f';
和可以混淆的字符:
my @o = 'o', 'о', 'ο'; # ASCII o, Cyrillic o, Greek omicron
我可以轻松地构建正则表达式,以检测同构的短语“ foo”:
say 'Suspicious!' if $text ~~ / $f @o @o /;
但是,如果我不知道在编译时要检测的值,该如何编写这样的正则表达式?假设我要检测包含消息中包含同形字母“现金”字词的网络钓鱼。我可以使用所有替代方法构建序列:
my @lookup = ['c', 'с', 'ϲ', 'ς'], ['a', 'а', 'α'], 's', 'h'; # arbitrary runtime length
现在显然,以下解决方案无法将数组元素“解包”为正则表达式:
/ @lookup / # doing LTM, not searching elements in sequence
我可以通过手动引用每个元素并撰写替代文本组成的文本表示来获得可作为正则表达式求值的字符串来解决此问题。然后使用字符串插值从中构建令牌:
my $regexp-ish = textualize( @lookup ); # string "[ 'c' | 'с' | 'ϲ' | 'ς' ] [ 'a' | 'а' | 'α' ] 's' 'h'"
my $token = token { <$regexp-ish> }
但这很容易出错。是否有任何更清洁的解决方案可以根据编译时未知的任意数量的元素动态编写正则表达式?
我不确定这是最佳使用方法。
我尚未在中实现可混淆1模块Intl::
,尽管我确实计划最终解决该问题,但我可以通过两种不同方式想象令牌的外观。2
my token confusable($source) {
:my $i = 0; # create a counter var
[
<?{ # succeed only if
my $a = self.orig.substr: self.pos+$i, 1; # the test character A
my $b = $source.substr: $i++, 1; # the source character B and
so $a eq $b # are the same or
|| $a eq %*confusables{$b}.any; # the A is one of B's confusables
}>
. # because we succeeded, consume a char
] ** {$source.chars} # repeat for each grapheme in the source
}
在这里,我使用了%*confusables
将以某种方式填充的动态哈希-这将取决于您的模块,甚至可能不一定是动态的(例如,具有签名:($source, %confusables)
或引用模块变量等)。
然后,您可以使代码工作如下:
say $foo ~~ /<confusable: 'foo'>/
这可能是最好的处理方式,因为它可以给您更多的控制权–我在您的模块上达到了顶峰,很明显,您希望启用2对1字形关系,最终您可能希望成为直接在字符上运行代码。
如果您对一对一关系没关系,可以使用一个更简单的令牌:
my token confusable($source) {
:my @chars = $source.comb; # split the source
@( # match the array based on
|( # a slip of
%confusables{@chars.head} # the confusables
// Empty # (or nothing, if none)
), #
@a.shift # and the char itself
) #
** {$source.chars} # repeating for each source char
}
该@(…)
结构使您可以有效地创建要内插的临时数组。在这种情况下,我们只需将易混淆内容与原始内容放在一起,就是这样。不过,您必须要小心,因为不存在的哈希项将返回类型对象,(Any)
并且在这里将事情弄乱了(因此// Empty
)
无论哪种情况,您都希望将参数与令牌一起使用,因为动态构造正则表达式充满了潜在的陷阱和插值错误。
1 Unicode称同形异义词为“视觉上相似的字符”和“易混淆的字符”。
2这里的动态哈希%confusables
可以通过多种方式填充,并且不一定是动态的,因为它可以通过参数(使用类似:($source, %confusables)
或引用模块变量的签名)来填充。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句