redhotpenguin has asked for the wisdom of the Perl Monks concerning the following question:
Monks,
I came across the need tonight to make email addresses such as mary@supercalifradulistic.org into a form like mary@superc... This isn't something used to obfuscate mailing list addresses, but more to make them short so they fit on a web page nicely.
I chained a few map statements together with a concatenation, and called the email via accessor from an object. This works, but as an exercise I'm wondering how you would approach this.
@shortened_email_addresses =
map { $_ . '...' } # add three dots to the end
map { $_ =~ m/^(\S+@\S{6})/ } # match the first 6 after @
map { $_->email } # call the email accessor
@objects;
Re: Shorten email address
by aukjan (Friar) on Jun 10, 2005 at 06:48 UTC
|
| [reply] |
Re: Shorten email address
by robartes (Priest) on Jun 10, 2005 at 07:17 UTC
|
One other, fairly brutal and ugly, way of doing this is by playing substr games:
#!/usr/local/bin/perl -w
use strict;
my $email='goblins@under.the.floorboards.com';
my $length=15;
my $result= eval { substr($email, $length-3) = '...'; return $email };
print $@?$email:$result;
| [reply] [d/l] |
|
The problem with goblins is that they always come in hordes. This reply inspired me to see if I could take on a horde of goblins, and a slew of other possible scenarios. This is definitely brutal and ugly.
#!/usr/bin/perl
use strict;
use warnings;
my @emails = (
'foo@barcom', 'longontheleft@foo.com',
'foo@longontheright.com', 'equalonbothsides@equalonbothsides',
'almostequal@almostequa', 'a.horde.of.goblins@under.the.floorboard
+s.com',
'goblins@under.the.floorboards.com'
);
my $MAXLENGTH = 16;
my $NUMDOTS = 3;
my %emails;
foreach my $email (@emails) {
$emails{$email}{'length'} = length($email);
if ( $emails{$email}{'length'} <= $MAXLENGTH ) {
print "No need to shorten $email\n";
next;
}
( $emails{$email}{'left'}, $emails{$email}{'right'} ) =
split( '@', $email );
if ( ( ( $NUMDOTS + length( $emails{$email}{'right'} ) ) > ($MAX
+LENGTH) )
&& ( ( $NUMDOTS + length( $emails{$email}{'left'} ) ) > ($MAXL
+ENGTH) ) )
{
print "Shorten both sides\n";
# Shorten the left side
substr(
$emails{$email}{'left'},
$MAXLENGTH - ( $MAXLENGTH / 2 ) - $NUMDOTS - 1,
length( $emails{$email}{'left'} )
)
= '.' x $NUMDOTS;
# Shorten the right side
substr(
$emails{$email}{'right'},
$MAXLENGTH - ( $MAXLENGTH / 2 ) - $NUMDOTS - 1,
length( $emails{$email}{'right'} )
)
= '.' x $NUMDOTS;
}
elsif (
(
length( $emails{$email}{'left'} ) -
length( $emails{$email}{'right'} )
) > $NUMDOTS
)
{
print "Shortening left side\n";
substr(
$emails{$email}{'left'},
$MAXLENGTH - length( $emails{$email}{'right'} ) - $NUMDOTS
+ - 1,
length( $emails{$email}{'left'} )
)
= '.' x $NUMDOTS;
}
else {
print "Shortening right side\n";
substr(
$emails{$email}{'right'},
$MAXLENGTH - length( $emails{$email}{'left'} ) - $NUMDOTS
+- 1,
length( $emails{$email}{'right'} )
)
= '.' x $NUMDOTS;
}
$emails{$email}{'short'} =
join( '@', $emails{$email}{'left'}, $emails{$email}{'right'} );
print "Shortened version ", $emails{$email}{'short'}, " is ",
length( $emails{$email}{'short'} ), " characters long.\n";
}
1;
__END__
No need to shorten foo@barcom
Shortening left side
Shortened version longo...@foo.com is 16 characters long.
Shortening right side
Shortened version foo@longonthe... is 16 characters long.
Shorten both sides
Shortened version equa...@equa... is 15 characters long.
Shortening right side
Shortened version almostequal@a... is 16 characters long.
Shorten both sides
Shortened version a.ho...@unde... is 15 characters long.
Shortening right side
Shortened version goblins@under... is 16 characters long.
| [reply] [d/l] |
Re: Shorten email address
by monarch (Priest) on Jun 10, 2005 at 07:27 UTC
|
$email =~ s!(\.)!<wbr />$1!g;
I only mention it because I've found myself doing this a lot.. | [reply] [d/l] [select] |
Re: Shorten email address
by ww (Archbishop) on Jun 10, 2005 at 13:33 UTC
|
Tell me I'm missing something (as, in fact, I suspect).
I ask because I fail to see what good the shortened forms will be, within the context of your "short so they fit on a web page nicely."
If RENDERING the too-long address borks the appearance of the webpage, just don't render it.... (with apologies to a former US President's spouse). i_m_a_way_too_long_address@goblins_under_the_floor_and_in_the_attic.org> can be rendered without harm (that I see offhand) briefly... but the mailto: (if that's what you're working on) STILL needs to be <a href="mailto:i_m_a_way_too_long_address@goblins_under_the_floor_and
+_in_the_attic.org>(renderedname)</a>
while the link that's displayed gets turned into "drop a line to goblins" or "joe's email" or "email1" or...
"Beating a dead horse" here: if you shorten the full email address to put in the mailto:, it's not gonna' work ...unless you create another process to retrieve the original (perhaps by searching a db created after adding yet more code to ensure that no "shortened" form matches a previously created but distinct address).
So, as I said to begin with, what am I missing, here? | [reply] [d/l] |
Re: Shorten email address
by spurperl (Priest) on Jun 10, 2005 at 06:49 UTC
|
Some thoughts:
- Folding it into a single loop could be more efficient.
- What about addresses like supercoderhaxor@np.net ?
| [reply] |
|
supercoderhaxor@np.net could be condensed to like 'superc...@np.net'. Thinking about this more it seems like I would want to introduce a constant length, and condense the address on either side of the @ sign to fit that length.
| [reply] |
|
| [reply] |
|
Yes, one approach could be set a constant length and then shorten both sides: 1 char for the @, 1 for the dot, 2-4 for the ending, plus at least one char for each name and domain - that's minimum 8 chars. For 10 chars, you can set the length of the name/domain to 2 each, etc. Depends on your specific needs.
| [reply] |
Re: Shorten email address
by QM (Parson) on Jun 10, 2005 at 15:20 UTC
|
map { $_ =~ m/^(\S+@\S{6})/ } # match the firs
+t 6 after @
That matches exactly 6 (non-whitespace) characters after the @...not 7, not 5, but exactly 6.
While this works for most, it won't work for me@x.tv. So your @shortened_email_addresses won't match one-to-one with @objects, and you might end up creating wrong mailto: links.
Use m/^(\S+@\S{1,6})/ instead.
-QM
--
Quantum Mechanics: The dreams stuff is made of
| [reply] [d/l] [select] |
Re: Shorten email address
by TedPride (Priest) on Jun 10, 2005 at 17:58 UTC
|
The following works fine.
EDIT: While working fine, my previous algorithm didn't preserve as much of the left part of the email as I wanted. The below is simpler and smarter:
use strict;
use warnings;
my ($ex, $ex1, $ex2, @test);
my $length = 14;
for $ex1 (1..15) {
for $ex2 (5..15) {
push @test, 'a' x $ex1 . '@' . 'b' x $ex2;
}
}
for (@test, <DATA>) {
chomp;
if (length($_) > $length) {
$ex = length($_) - $length + 3;
@_ = split /@/;
if (length($_[1]) > $ex) {
substr($_[1], length($_[1]) - $ex, $ex) = '...';
}
else {
$ex += 3;
$ex2 = length($_[1]) - 1;
$ex1 = $ex - $ex2;
if ($ex1 < 4) {
$ex1 = 4;
$ex2 = $ex - $ex1;
}
substr($_[0], length($_[0]) - $ex1, $ex1) = '...';
substr($_[1], length($_[1]) - $ex2, $ex2) = '...';
}
$_ = join '@', @_;
}
print "$_\n";
}
__DATA__
ted@dingos.com
mary@supercalifradulistic.org
i.am.a.purple.dinosaur@barney.must.die.com
EDIT: My previous algorithm determined how many characters needed to be removed. Then it divided those between the two sides of the emai based on how long each side was. If the left part was smaller than 4 characters, it gave everything to the right. If the right part was smaller than 4, it gave everything to the left. If both sides were in use, it added 3 characters and recalculated (since you needed two sets of ...).
The problem with this approach is it took away too much from the left side, which you want preserved if at all possible. My second algorthm (seen above), gives everything to the right side unless the right side is too short, in which case it adds 3 and gives the extra to the left, and if the left is too short for that, it gives 4 to the left and the rest to the right. I included all significant test cases so you can see what it's doing. | [reply] [d/l] |
|
| [reply] |
Re: Shorten email address
by TheMadScientist (Initiate) on Feb 16, 2011 at 22:53 UTC
|
I'd probably approach it the easy way just use an email shortener to get a shorter email address. lol | [reply] |
|
|