2014-11-21 116 views
1

前言:这是一个学校作业。我没有试图收集电子邮件用于恶意目的。正则表达式转换混淆电子邮件地址Perl

我需要识别,提取和转换来自给定文件的电子邮件地址(作为命令行 参数)。对于模糊的电子邮件地址,我需要将电子邮件转换回常规电子邮件地址格式(account-name @ domain-name)。

这些都是混淆技术,我需要考虑:

No obfuscation. An email address may be included in a pair of <>. For example, 
1. <[email protected]> or [email protected] 
2. A space MAY be added before or after (or both) the @ sign. 
3. The @ sign is written as AT or at, and space is added before and after AT or at. 
4. The . sign in domain name is written as DOT or dot, and space is added before and after DOT 
or dot. 

目前我只是想占第一种技术。 "1. <[email protected]> or [email protected]"

这是我到目前为止有:

编辑:从@ikegami

#!/usr/bin/perl -w 

use warnings; 
use strict; 

my @addrs; 
my $re; 
open my $INFILE, '<', $ARGV[0] or die $!; 

while(my $line = <$INFILE>) { 
    push @addrs, $line =~ /(\w+\@(?:\w+\.)*\w+)/g; 

foreach $re (@addrs) { 
    if ($re =~ (/$line/)) { 
     print $re; 
    } 
} 
} 


close $INFILE; 

使用帮助不再得到一个错误,但是没有得到任何输出。

样品输入:

Email: <[email protected]> email: [email protected] [email protected] 
Email: anonym3 AT efs.new.edu E-mail: anonym4 at efs.new.edu test at 9:00PM 
We will have a test in room 705 @ another time. 
Email: anonym5 @ efs dot new dot edu what if we continue 
Another test anonym6 at efs dot new dot edu 
If you type a dot, it means you have finished typing all contents. 
Email:anonym7 AT new DOT efs DOT edu 
We can, at 10:00PM, go to library DOT or . 
My gmail address is [email protected] DOT com 

输出应该是:

[email protected] 
[email protected] 
[email protected] 
anonym3[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 

任何帮助/在正确的方向点,将不胜感激!

+5

您是否想过,也许这些人为解决他们的电子邮件地址出于某种原因而变得非常重要? – xbug 2014-11-21 19:38:57

+1

第一个'syntax'错误是因为'$ str =〜s \ w + @ \ w + \。\ W +(。\ W +)*; ''=''正则表达式运算符需要分隔符,'=〜/ regex /;'除此之外,您要通过foreach循环覆盖没有任何内容的$ str。 – sln 2014-11-21 19:43:53

+0

哦,我看到@sln我更新了解决方案/错误输出。仍然有问题。 – chomp 2014-11-21 19:53:34

回答

3

downvotes可能与问题的主题有关:你似乎正在努力解决人们试图避免收集他们的电子邮件地址的问题。人们通常会混淆他们的地址,因为他们不希望他们收获。因此,无论您提出哪种解决方案,都可能违反发布混淆地址的人的意图。然而,教授选择一个不受欢迎的话题并不是你的错。

移动过去那种....

在文本检测混淆的电子邮件地址是一个不完美的科学,以及一定程度上的军备竞赛。即使检测到有效的电子邮件地址也很棘手。将会出现误报,并可能出现假阴性。即使有一个相当不错的电子邮件地址列表,仍然可能存在技术上可能正确但实际上无用的地址。

CPAN模块Email :: Address很擅长解析电子邮件地址的文本,但它带有误报。电子邮件::有效的是拒绝许多这些误报。这里是产生你要找的输出的例子:

use Email::Address; 
use Email::Valid; 

while(<DATA>) { 
    print "$_\n" for 
    grep { Email::Valid->address($_->address) } 
     Email::Address->parse(fix_common_obfu($_)); 
} 

sub fix_common_obfu { 
    my $string = shift; 
    $string =~ s/\s+dot\s+/./ig;  # Turn ' dot ' into '.' 
    $string =~ s/\[email protected]\s+|\s+at\s+/@/ig; # Turn ' @ ' or ' at ' into '@'. 
    return $string; 
} 

__DATA__ 
Email: <[email protected]> email: [email protected] [email protected] 
Email: anonym3 AT efs.new.edu E-mail: anonym4 at efs.new.edu test at 9:00PM 
We will have a test in room 705 @ another time. 
Email: anonym5 @ efs dot new dot edu what if we continue 
Another test anonym6 at efs dot new dot edu 
If you type a dot, it means you have finished typing all contents. 
Email:anonym7 AT new DOT efs DOT edu 
We can, at 10:00PM, go to library DOT or . 
My gmail address is [email protected] DOT com 

这将产生以下的输出:

[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 

UPDATE:

这里是一个(不太可靠,但工作)解决方案,避免使用外部CPAN模块,使用正则表达式解决核心问题。

while(<DATA>) { 
    s/\[email protected]\s*|\s*@\s+/@/g; # Deal with spaces around @. 
    s/\s+at\s+/@/ig;   # Deal with " at " 
    s/\s+dot\s+/./ig;   # Deal with " dot " 
    while (
    m/(   # Match and capture. 
     [^<\s:]+ # One or more characters except <, space, or :. 
     @   # Literal '@' 
     \S+   # One or more non-space. 
     \.   # Require a dot in the domain. 
     [^>\s]+  # One or more any character except whitespace or '>'. 
    )/gx   # Repeat as many matches as found, allow freeform. 
) { 
    print "$1\n"; 
    } 
} 

__DATA__ 
.... etc etc etc... 

我用/x改性剂,以允许正则表达式是自由形式的(不重要的空白,并允许注释)。这使得它可以分解成更小的更清晰的块。

+0

首先,感谢您的帮助!但是,何时实现这一点,我得到了什么似乎是错误的“使用功能”说';“。我需要一个特定版本的perl吗?我正在使用5.8.8 @DavidO – chomp 2014-11-21 21:05:30

+1

我删除了'说'的用法。直到2007年12月发布的Perl 5.10才被引入到Perl中。您的Perl版本已经有8年的历史了。无论如何,这应该现在工作得很好。 – DavidO 2014-11-21 21:08:02

+0

不幸的是,我正在使用我的学校给我的东西。它看起来像我可能无法使用“电子邮件::地址;”无论是。我会尝试升级,但我假设,如果我的教授试图编译他的旧版本,它不会为他工作。这是我的错误消息:“AT'INC中找不到Email/Address.pm('AT'INC包含:/usr/lib64/perl5/site_perl/5.8。8/x86_64-linux-thread-multi /usr/lib/perl5/site_perl/5.8.8“.....(继续前进)@DavidO – chomp 2014-11-21 21:15:26

1

很难解释你做错了什么,因为它有这么多,所以我只是要提供一些正确的代码。这将扫描的电子邮件类型之一:

my @addrs; 
while (my $line = <$INFILE>) { 
    push @addrs, $line =~ /(\w+\@(?:\w+\.)*\w+)/g; 
} 

或只是

my @addrs; 
while (<$INFILE>) { 
    push @addrs, /(\w+\@(?:\w+\.)*\w+)/g; 
} 

提示:由于你接受读取文件作为参数,你还不如用<>。更换

open my $INFILE, '<', $ARGV[0] or die $!; 
while (<$INFILE>) { 
    ... 
} 

while (<>) { 
    ... 
} 

它会从指定的命令行上的文件,或者STDIN读,如果没有提供任何文件。所以它更简单,更好!

+0

非常感谢您的帮助!我更新了我的代码。但是,虽然我现在没有错误,但我也没有输出。也许,我在打印时没有正确使用“@addrs”? @ikegami – chomp 2014-11-21 21:28:31

+0

也许吧。我怎么知道? '@addrs'打印(“$ _ \ n”);'每行显示一行。 – ikegami 2014-11-21 21:30:04

+0

它也在原始文章中更新。你可以在那里看到代码。 @ikegami – chomp 2014-11-21 21:32:53

相关问题