使用 Template Toolkit 从字符串中提取电子邮件
Extract email from string using Template Tookit
我猜这比较简单,但我找不到答案。
从 '"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'
};
我的代码,基于下面的 帮助,其中 $VAR1
是 dumper.dump(item.from)
的输出
[% text = item.from -%]
[% IF (matches = text.match('(.*?)(\s)?+<(.*?)>')) -%]
<td>[% matches.1 %]</td>
[% ELSE -%]
<td>[% text %]</td>
[% END %]
但是,它仍然不匹配 $VAR1
我不知道 Template Toolkit 可以如何帮助您。使用 Email::Address or Email::Address::XS 解析电子邮件地址。
有一个非常古老(且未维护)的模块,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 代码中执行的操作。您应该在模板外部解析数据并将其传递给变量,或者您应该传递一个可以从模板内部调用的解析子例程。
但是,在给了你警告之后,如果你仍然坚持这是你想做的,那么你可以这样做:
在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)
。所以我在名称和左尖括号之间得到 space。
你可能不想在你的 matches
数组中匹配 whitespace,所以我会删除它周围的括号,使正则表达式 (.*?)\s*<(.*?)>
(注意\s*
是表示“零个或多个白色 space 字符”)的更简单方式。
您现在可以使用 matches.0
获取姓名并使用 matches.1
获取电子邮件地址。
哦,没有必要将 items.from
复制到 text
。您可以在任何标量变量上调用 matches
vmethod,因此使用它可能更简单:
[% matches = item.from.match(...) -%]
我有没有提到这是一个非常糟糕的想法? :-)
更新2:
如果您按照我为您提供的方式提供完整的 运行可用代码示例,这一切都会变得容易得多。任何时候我必须编辑一些东西以获得示例 运行ning,我们 运行 冒着我错误地猜测您的代码如何工作的风险。
但是,考虑到这一点,这是我最新的测试模板:
[% 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:
我再次尝试合并您所说的更改。但同样,我不得不猜测一些东西,因为你没有分享完整的 运行nable 示例。再一次,我的代码按预期工作。
[% 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'
];
这样就可以了。如果您需要更多帮助,请发送完整的 运行nable 示例。如果你不那样做,我就帮不了你了。
我猜这比较简单,但我找不到答案。
从 '"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'
};
我的代码,基于下面的 $VAR1
是 dumper.dump(item.from)
[% text = item.from -%]
[% IF (matches = text.match('(.*?)(\s)?+<(.*?)>')) -%]
<td>[% matches.1 %]</td>
[% ELSE -%]
<td>[% text %]</td>
[% END %]
但是,它仍然不匹配 $VAR1
我不知道 Template Toolkit 可以如何帮助您。使用 Email::Address or Email::Address::XS 解析电子邮件地址。
有一个非常古老(且未维护)的模块,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 代码中执行的操作。您应该在模板外部解析数据并将其传递给变量,或者您应该传递一个可以从模板内部调用的解析子例程。
但是,在给了你警告之后,如果你仍然坚持这是你想做的,那么你可以这样做:
在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)
。所以我在名称和左尖括号之间得到 space。
你可能不想在你的 matches
数组中匹配 whitespace,所以我会删除它周围的括号,使正则表达式 (.*?)\s*<(.*?)>
(注意\s*
是表示“零个或多个白色 space 字符”)的更简单方式。
您现在可以使用 matches.0
获取姓名并使用 matches.1
获取电子邮件地址。
哦,没有必要将 items.from
复制到 text
。您可以在任何标量变量上调用 matches
vmethod,因此使用它可能更简单:
[% matches = item.from.match(...) -%]
我有没有提到这是一个非常糟糕的想法? :-)
更新2:
如果您按照我为您提供的方式提供完整的 运行可用代码示例,这一切都会变得容易得多。任何时候我必须编辑一些东西以获得示例 运行ning,我们 运行 冒着我错误地猜测您的代码如何工作的风险。
但是,考虑到这一点,这是我最新的测试模板:
[% 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:
我再次尝试合并您所说的更改。但同样,我不得不猜测一些东西,因为你没有分享完整的 运行nable 示例。再一次,我的代码按预期工作。
[% 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'
];
这样就可以了。如果您需要更多帮助,请发送完整的 运行nable 示例。如果你不那样做,我就帮不了你了。