Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将文本与模板进行比较以检测异常(反向模板)_Python_Perl_Validation_Templates_Text - Fatal编程技术网

Python 将文本与模板进行比较以检测异常(反向模板)

Python 将文本与模板进行比较以检测异常(反向模板),python,perl,validation,templates,text,Python,Perl,Validation,Templates,Text,我正在寻找一个算法,甚至是一个算法空间,来处理验证短文本(电子邮件)是否与已知模板匹配的问题。编码可能是python或perl,但这是灵活的 问题是: 能够访问生产数据的服务器需要能够发送电子邮件到Internet: Dear John Smith, We received your last payment for $123.45 on 2/4/13. We'd like you to be aware of the following charges: $12.34 Spuzn

我正在寻找一个算法,甚至是一个算法空间,来处理验证短文本(电子邮件)是否与已知模板匹配的问题。编码可能是python或perl,但这是灵活的

问题是:

能够访问生产数据的服务器需要能够发送电子邮件到Internet:

Dear John Smith,

We received your last payment for $123.45 on 2/4/13. We'd like you to be aware of the following charges:
      $12.34 Spuznitz, LLC on 4/1
      $43.21 1-800-FLOWERS on 4/2
As always, you can view these transactions in our portal. 
Thank you for your business!
显然,一些电子邮件内容会有所不同——称呼语(“约翰·史密斯”)、“2013年2月4日123.45美元”,以及打印交易的行。其他部分(“我们收到了您上次的付款”)非常静态。我希望能够匹配文本的静态部分,并量化动态部分是否在某些合理的范围内(例如,我可能知道要打印的大多数事务行是5行)

因为我担心数据外泄,所以我想确保与此模板不匹配的电子邮件永远不会发出——我想检查电子邮件并隔离任何与我预期不符的内容。因此,我需要自动进行模板匹配,并阻止任何距离匹配足够远的电子邮件

所以问题是,我在哪里寻找过滤机制?贝叶斯过滤试图验证特定消息和非特定语料库之间是否有足够的相似性,这是一种相反的问题。Perl的模板模块之类的东西是紧密匹配的——但用于输出,而不是用于输入或比较。简单的“diff”类型比较无法很好地处理有限的动态信息


如何测试这些传出的电子邮件是否“像鸭子一样嘎嘎”呢?

如果您想将预先存在的模板与控制流元素(例如,
{%x in y%}
等)匹配,并根据它的假设输出,您必须解析模板语言-这似乎需要大量工作

另一方面,如果您准备为验证目的编写第二个模板,例如:

亲爱的{{customer},
我们在{{full date}收到您上次支付的{{currency}}款项。我们希望您了解以下费用:
({{currency}{{supplier}}{{short date}}}
){,5}一如既往,您可以在我们的门户中查看这些事务\。
。。。这只是正则表达式语法的一个简单扩展,很容易将一些东西组合在一起进行验证:

重新导入
字段={
“客户”:r“[\w\s\.-]{,50}”,
“供应商”:r“[\w\s\,-]{,30}”,
“货币”:r“[$)]\d+\.\d{2}”,
“短日期”:r“\d{,2}/\d{,2}”,
“完整日期”:r“\d{,2}/\d{,2}/\d{2}”,
}
def验证(例如,模板文件):
打开(模板文件)作为f:
模板=f.read()
对于标记,字段中的模式。项()
template=template.replace(“{{%s}}”%tag,pattern)
valid=re.compile(模板+“$”)
返回(re.match(有效,示例)不是None)

无论如何,上面的示例都不是有史以来最伟大的Python代码,但它足以让大家了解一般的想法。

您可以使用语法进行紧密匹配。可以用语法组织regexp,以便于抽象:

或者你可以使用专用的语法引擎

如果你想要更统计的方法,考虑一下。首先,标记文本并用有意义的占位符替换变量块,如

CURRENCY
DATE
。然后,构建n-gram。现在您可以使用来比较两个文本

下面是一个纯Perl实现,它可以在三角图上工作:

#!/usr/bin/env perl
use strict;
use utf8;
use warnings;

my $ngram1 = ngram(3, tokenize(<<'TEXT1'));
Dear John Smith,

We received your last payment for $123.45 on 2/4/13. We'd like you to be aware of the following charges:
      $12.34 Spuznitz, LLC on 4/1
      $43.21 1-800-FLOWERS on 4/2
As always, you can view these transactions in our portal. 
Thank you for your business!
TEXT1

my $ngram2 = ngram(3, tokenize(<<'TEXT2'));
Dear Sally Bates,

We received your last payment for $456.78 on 6/9/12. We'd like you to be aware of the following charges:
      $123,43 Gnomovision on 10/1
As always, you can view these transactions in our portal. 
Thank you for your business!
TEXT2

my %intersection =
    map { exists $ngram1->[2]{$_} ? ($_ => 1) : () }
    keys %{$ngram2->[2]};
my %union =
    map { $_ => 1 }
    keys %{$ngram1->[2]}, keys %{$ngram2->[2]};

printf "Jaccard similarity coefficient: %0.3f\n", keys(%intersection) / keys(%union);

sub tokenize {
    my @words = split m{\s+}x, lc shift;

    for (@words) {
        s{\d{1,2}/\d{1,2}(?:/\d{2,4})?}{ DATE }gx;
        s{\d+(?:\,\d{3})*\.\d{1,2}}{ FLOAT }gx;
        s{\d+}{ INTEGER }gx;
        s{\$\s(?:FLOAT|INTEGER)\s}{ CURRENCY }gx;
        s{^\W+|\W+$}{}gx;
    }

    return @words;
}

sub ngram {
    my ($size, @words) = @_;
    --$size;

    my $ngram = [];
    for (my $j = 0; $j <= $#words; $j++) {
        my $k = $j + $size <= $#words ? $j + $size : $#words;
        for (my $l = $j; $l <= $k; $l++) {
            my @buf;
            for my $w (@words[$j..$l]) {
                push @buf, $w;
            }
            ++$ngram->[$#buf]{join(' ', @buf)};
        }
    }

    return $ngram;
}
#/usr/bin/env perl
严格使用;
使用utf8;
使用警告;
my$ngram1=ngram(3,标记化(1):()}
键%{$ngram2->[2]};
我的%联盟=
映射{$\=>1}
键%{$ngram1->[2]},键%{$ngram2->[2]};
printf“Jaccard相似系数:%0.3f\n”,键(%intersection)/键(%union);
子标记化{
my@words=splitm{\s+}x,lc移位;
for(@words){
s{\d{1,2}/\d{1,2}(?:/\d{2,4})}{DATE}gx;
s{\d+(?:\,\d{3})*\.\d{1,2}}{FLOAT}gx;
s{\d+}{INTEGER}gx;
s{\$\s(?:FLOAT | INTEGER)\s}{CURRENCY}gx;
s{^\W+|\W+$}{}gx;
}
返回@words;
}
子内存{
我的($size,@words)=;
--$size;
我的$ngram=[];
对于(my$j=0;$j我会选择“最长公共子序列”。可以在这里找到标准实现:

如果您需要更好的算法和/或更多关于字符串不精确匹配的想法,标准参考是本书:


不要被标题所愚弄。计算生物学主要是关于长字符串(也称为DNA序列)的大型数据库的匹配。

仅与regexp匹配有什么错?您可以在电子邮件to very和模板之间找到最长的公共子序列(甚至是要验证的电子邮件和另一封电子邮件之间)。所有电子邮件的结果都应该相同或几乎相同。另外:如果隔离电子邮件,它将准确地找到您需要检查的部分。使用基于语法的解析器生成器。我不是Python专家,但似乎有一个基于语法的解析库可能会有所帮助:@creakative我认为基于语法的解析是有效的erkill解决了这个问题…但每个人都有自己的问题:-)然而,你实际上从零开始就实现了一个简单的语法;)你的意思是吗?因为子序列是,这意味着它应该非常非常小心地用于批处理任务!为什么你认为LCS是NP难的?维基百科列出了P时间算法,甚至比O(n^2)更好(n=较长序列的长度)。我指的是。最长的公共子字符串确实可以。谢谢,回答得好-不是因为它为我提供了一个真实的答案,而是它帮助我更好地理解解决方案空间,以便我可以进行修补。不客气:)对于自然语言处理来说,没有一个“一刀切”的答案,即使是简单的任务也需要一些修补。@gowenfawr,我刚刚发现了这个模块。突然,它