#后缀数组 #文本 #NLP #词典 #匹配 #目标

app lexmatch

这是一个简单的词典匹配工具,给定一个单词或短语的词典,识别给定目标文本中的所有匹配项。使用后缀数组。

3个版本 (破坏性)

0.3.0 2024年7月3日
0.2.0 2024年2月6日
0.1.0 2021年9月21日

655文本处理

Download history 111/week @ 2024-07-02

每月124次下载

GPL-3.0+

32KB
519

Lexmatch

这是一个简单的词典匹配工具,给定一个单词或短语的词典,识别给定目标文本中的所有匹配项,并返回它们的精确位置。它可用于计算词典在目标语料库中的频率列表。

实现使用后缀数组或哈希表。文本必须是纯文本UTF-8。对于前者实现(默认),限制为2^32字节(约4GB)。对于后者实现(--tokens/--cjk),没有此类限制。输出的偏移量将是UTF-8 字节位置。

此工具仅进行精确(或大小写不敏感)匹配,如果您需要对词典进行模糊匹配,请查看analiticcl

安装

您可以使用Rust的包管理器构建和安装最新稳定版本

cargo install lexmatch

或者如果您想克隆此仓库后使用开发版本

cargo install --path .

系统上还没有 cargo/rust?在基于 Debian/ubuntu 的系统上,请在 sudo apt install cargo,在 macOS 上,请在 brew install rust,或使用 rustup

用法

请参阅 lexmatch --help

简单示例

$ lexmatch --lexicon lexicon.lst corpus.txt

词典必须是纯文本UTF-8,每行一个条目,条目不一定是单个单词,长度也不受限制。如果词典由制表符分隔值(TSV)组成,则仅考虑第一列,其余忽略。

除了词典外,您还可以使用 --query 在命令行上提供要查询的模式。

默认情况下,您将获得一个TSV文件,其中包含文本列、出现次数列以及每个匹配项的起始位置列(UTF-8字节位置,动态列)

$ lexmatch --query good --query bad /nettmp/republic.short.txt 
Reading text from /tmp/republic.short.txt...
Building suffix array (this may take a while)...
Searching...
good    4       193     3307    3480    278
bad     3       201     3315    3488

默认情况下,匹配是区分大小写的,若要启用不区分大小写的匹配,请添加--no-case(所有输入和输出将转换为小写,在极少数情况下可能导致UTF-8偏移量在原始文本中不再有效)。

对于详细输出,请添加--verbose。这将产生更干净的TSV(制表符分隔值)输出,您可以轻松导入,例如在STAM工具中。

$ lexmatch --verbose --query good --query bad /nettmp/republic.short.txt
Text    BeginUtf8Offset EndUtf8Offset
Reading text from /tmp/republic.short.txt...
Building suffix array (this may take a while)...
Searching...
good    193     197
good    3307    3311
good    3480    3484
good    278     282
bad     201     204
bad     3315    3318
bad     3488    3491

您可以提供多个词库以及多个测试文件,输出将输出词库和/或测试文件。如果多个词库匹配,它们都会返回(以分号分隔)。结果顺序是任意的。

如果您不关心精确的位置,而只想计算词库中每个项目的出现次数,或者通过--query传递,请传递--count-only

$ lexmatch --count-only --query good --query bad /tmp/republic.short.txt
Reading text from /tmp/republic.short.txt...
Building suffix array (this may take a while)...
Searching...
good    4
bad	3

您可以使用--freq配置最小频率阈值。

除了将整个词库与文本匹配之外,您还可以遍历文本中的标记,并检查它们是否出现在词库中。这使用哈希表而不是后缀数组,通常更快。然而,它更加有限,不能与频率阈值或计数一起使用。它将始终产生详细输出(类似于--verbose)。

$ lexmatch --tokens --query good --query bad /nettmp/republic.short.txt
Text    BeginUtf8Offset EndUtf8Offset
Reading text from /tmp/republic.short.txt...
good    193     197
bad     201     204
good    278     282
good    3307    3311
bad     3315    3318
good    3480    3484
bad     3488    3491

与之前不同,现在您会发现匹配项现在是按阅读顺序返回的。

如果您添加了--coverage,那么您将获得一个包含一些覆盖率统计数据的额外最后一行。这有助于查看文本中有多少部分被您的词库所覆盖。

#coverage (tokens) = 7/627 = 0.011164274322169059

覆盖率也可以逐行计算,并针对多个词库进行匹配,我们还可以通过传递-作为文件名来直接从stdin读取,而不是从文件读取。

$ echo "Is this good or bad?\nIt is quite good." | lexmatch --coverage-matrix --query good --query bad  -
Reading text from -...
Line            query
Is this good or bad?    0.4
It is quite good.       0.25

这可以作为简单的基于词库的语言检测方法。

$ echo "Do you know what language this is?\nUnd was ist das hier genau?\nÇa va assez bien je crois" | lexmatch -i  --coverage-matrix --lexicon ~X/en.lst --lexicon ~X/de.lst --lexicon ~X/fr.lst  -                     
Reading lexicon...
Reading lexicon...
Reading lexicon...
Reading text from -...
Line            /home/proycon/exp/en.lst        /home/proycon/exp/de.lst        /home/proycon/exp/fr.lst        Total
do you know what language this is?      1       0       0.14285714285714285     1.1428571428571428
und was ist das hier genau?     0.16666666666666666     0.8333333333333334      0.16666666666666666     1.1666666666666667
ça va assez bien je crois       0.2     0.2     0.6     1

当使用--tokens(或--coverage-matrix)时,我们依赖于空白和标点符号来分隔标记。这对于像中文、日文和韩文这样的没有这样分隔的语言不起作用。对于这些语言,可以通过传递--cjk来达到类似的线性搜索行为,其中整数值表示要探索的最大字符长度。然后将执行贪婪搜索,优先考虑较长的模式而不是较短的模式。

依赖项

~1.5MB
~24K SLoC