【问题标题】:Extract email from string using Template Tookit使用模板工具包从字符串中提取电子邮件
【发布时间】:2021-06-19 14:02:23
【问题描述】:

我猜这个比较简单,但我找不到答案。

'"John Doe" <email@example.com>' 之类的字符串中 - 如何使用Template Tookit 从中提取电子邮件部分?

要解析的示例字符串如下:

$VAR1 = { 
    'date' => '2021-03-25',
    'time' => '03:58:18',
    'href' => 'https://example.com',
    'from' => 'fezius@evrostroyserov.ru on behalf of Caroline <fezius@evrostroyserov.ru>',
    'bytes' => 13620,
    'pmail' => 'user@example.com',
    'sender' => 'sender@example.com',
    'subject' => 'Some Email Subject'
};

我的代码,基于下面的@dave-cross 帮助,其中$VAR1dumper.dump(item.from) 的输出

[% text = item.from -%]
[% IF (matches = text.match('(.*?)(\s)?+<(.*?)>')) -%]
<td>[% matches.1 %]</td>
[% ELSE -%]
<td>[% text %]</td>
[% END %]

但是,它仍然不匹配 $VAR1

【问题讨论】:

  • 模板工具包用于填充网页或任何其他结构化文档,而不是从文本中提取信息。
  • 告诉我们更多关于您想要实现的目标,也许我们可以提供帮助。
  • 我可能应该使用“格式”这个词而不是提取。也许 TT 中的正则表达式只能获取电子邮件?
  • 不清楚你想做什么。如果您尝试从字符串中提取姓名和电子邮件,那么 my $data = '"John Doe" &lt;email@example.com&gt;'; my($name,$email) = $data =~ /"(.+?)" &lt;(.+?)&gt;/; 会产生所需的结果。
  • @DarioZadro:查看我的答案的更新。

标签: perl template-toolkit


【解决方案1】:

我不知道模板工具包如何为您提供帮助。使用Email::AddressEmail::Address::XS 解析电子邮件地址。

【讨论】:

    【解决方案2】:

    有一个非常古老(且未维护)的模块Template::Extract,让您定义一个模板,然后从可能由该模板生成的字符串向后工作:

    use Template::Extract;
    use Data::Dumper;
    
    my $obj = Template::Extract->new;
    my $template = qq("[% name %]" <[% email %]>);
    
    my $string = '"John Doe" <email@example.com>';
    
    my $extracted = $obj->extract($template, $string);
    
    print Dumper( $extracted );
    

    输出是:

    $VAR1 = {
              'email' => 'email@example.com',
              'name' => 'John Doe'
            };
    

    但是,有些模块已经为您完成这项工作,并将处理更多情况

    【讨论】:

    • 这看起来是在正确的轨道上,但是您将如何在.tt 模板文件中执行此操作?
    • 好吧,我根本不会这样做。在模板文件中,您可以访问所有 Perl,因此您可以编写任何您想要的 Perl。但是,您应该在处理模板之前弄清楚所有这些东西,这样您就可以传递您需要的值。我认为您需要先解释一下为什么要从内而外地做事,然后才会有人评论您的所作所为。
    • 不幸的是,我只能访问模板文件。您能否编辑您的答案以显示如何直接在 .tt 文件中完成相同的操作?谢谢。
    • 我在template-toolkit.org/docs/modules/Template/Plugin/index.html 上没有看到活动插件,并且不确定您的答案是否有效。
    • 我的回答是尽我所能。同样,我不建议您使用它,而是说明您的实际问题以获得更好的建议。
    【解决方案3】:

    这可以满足您的需求,但它非常脆弱,而且这确实不是您应该在 TT 代码中做的事情。您应该获取在模板外部解析的数据并将其传递到变量中,或者您应该传入一个可以从模板内部调用的解析子例程。

    但是,在给你警告之后,如果你仍然坚持这是你想做的事,那么你可能会这样做:

    test.tt:

    [% text = '"John Doe" <email@example.com>';
       matches = text.match('"(.*?)"\s+<(.*?)>');
       IF matches -%]
    Name: [% matches.0 %]
    Email: [% matches.1 %]
    [% ELSE -%]
    No match found
    [% END -%]
    

    然后,使用tpage进行测试:

    $ tpage test.tt
    Name: John Doe
    Email: email@example.com
    

    但我不能再强调你不应该这样做。

    更新:我已使用此测试模板来调查您的进一步问题。

    [% item = { from => '"John Doe" <email@example.com>' };
       text = item.from -%]
    [% IF (matches = text.match('(.*?)(\s)?+<(.*?)>')) -%]
    <td>[% matches.1 %]</td>
    [% ELSE -%]
    <td>[% text %]</td>
    [% END %]
    

    运行它,我得到了这个:

    $ tpage test2.tt
    <td> </td>
    

    这就是我希望在比赛中看到的。您正在打印matches.1。这是matches 数组中的second 项。第二个匹配组是(\s)。所以我得到了名称和左尖括号之间的空格。

    您可能不希望 matches 数组中的空格匹配,所以我会删除它周围的括号,以制作正则表达式 (.*?)\s*&lt;(.*?)&gt;(请注意,\s* 是一种更简单的方式来表示“零或更多空白字符”)。

    您现在可以使用matches.0 获取姓名,使用matches.1 获取电子邮件地址。

    哦,没有必要将items.from 复制到text。您可以在任何标量变量上调用 matches vmethod,因此使用起来可能更简单:

    [% matches = item.from.match(...) -%]
    

    我有没有提到这是一个非常糟糕的想法? :-)

    更新2

    如果您以与我为您做的相同方式提供完整、可运行的代码示例,这一切都会变得容易得多。每当我必须编辑某些内容以使示例运行时,我们就有可能会错误地猜测您的代码是如何工作的。

    但是,请记住,这是我最新的测试模板:

    [% item = {
        'date' => '2021-03-25',
        'time' => '03:58:18',
        'href' => 'https://example.com',
        'from' => 'fezius@evrostroyserov.ru on behalf of Caroline <fezius@evrostroyserov.ru>',
        'bytes' => 13620,
        'pmail' => 'user@example.com',
        'sender' => 'sender@example.com',
        'subject' => 'Some Email Subject'
    };
       text = item.from -%]
    [% IF (matches = text.match('(.*?)(\s)?<(.*?)>')) -%]
    <td>[% matches.2 %]</td>
    [% ELSE -%]
    <td>[% text %]</td>
    [% END %]
    

    我已经更改了item 的定义以获取完整示例。我已经离开了正则表达式,就像我提出建议之前一样。而且(因为我没有更改正则表达式)我已将输出更改为打印matches.2 而不是matches.1.

    接下来会发生什么:

    $ tpage test3.tt
    <td>fezius@evrostroyserov.ru</td>
    

    所以它起作用了。

    如果您的代码不起作用,那么您需要确定我的(工作)代码和您的(非工作)代码之间的区别。我很乐意帮助您识别这些差异,但您必须给出您的非工作示例才能让我这样做。

    更新3

    我再次尝试合并您所说的更改。但同样,我不得不猜测一些东西,因为您没有共享完整的可运行示例。同样,我的代码按预期工作。

    [% USE dumper -%]
    [% item = {
        'date' => '2021-03-25',
        'time' => '03:58:18',
        'href' => 'https://example.com',
        'from' => 'fezius@evrostroyserov.ru on behalf of Caroline <fezius@evrostroyserov.ru>',
        'bytes' => 13620,
        'pmail' => 'user@example.com',
        'sender' => 'sender@example.com',
        'subject' => 'Some Email Subject'
    };
     -%]
    [% matches = item.from.match('(.*?)(\s)?<(.*?)>') -%]
    [% dumper.dump(matches) %]
    

    并对其进行测试:

    $ tpage test4.tt
    $VAR1 = [
              'fezius@evrostroyserov.ru on behalf of Caroline',
              ' ',
              'fezius@evrostroyserov.ru'
            ];
    

    这样就行了。如果您需要更多帮助,请发送一个完整的可运行示例。如果你不这样做,我将无法再帮助你。

    【讨论】:

    • 这让我更接近了。我会更新我的问题,希望您能提供答案来解决我的问题。
    • 谢谢你,戴夫。不幸的是,在调用dumper.dump(matches) 时,matches 变量始终为空。我现在放弃了这个方向,但会接受你的回答,因为它是最有帮助的。
    • @DarioZadro:您的示例代码与我的有何不同?如果您可以向我展示更多您的代码,我会尝试弄清楚发生了什么。
    • @DarioZadro:我不知道您所说的“我更新了$VAR1 以查看要解析的真实示例”是什么意思。 $VAR1 只是由 Data::Dumper 创建的虚拟输出。没有名为$VAR1 的实际变量。你能分享一些演示问题的实际代码吗?
    • @DarioZadro:那不是你的代码。这是从您的代码中提取的几个小片段。如果您需要更多帮助,请按照我为您提供的相同方式以完整、可运行的格式提供您的代码。
    猜你喜欢
    • 2023-03-31
    • 2017-10-10
    • 2013-11-22
    • 1970-01-01
    • 2013-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多