Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Shorten email address

by redhotpenguin (Deacon)
on Jun 10, 2005 at 06:39 UTC ( [id://465444]=perlquestion: print w/replies, xml ) Need Help??

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;

Replies are listed 'Best First'.
Re: Shorten email address
by aukjan (Friar) on Jun 10, 2005 at 06:48 UTC
    what would you do with mary.had.a.very.little.lamb@some.org ? Do you want to short it too ??

    .:| If it can't be fixed .. Don't break it |:.

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;

    CU
    Robartes-

      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.
Re: Shorten email address
by monarch (Priest) on Jun 10, 2005 at 07:27 UTC
    If it helps, I find the <wbr /> tag rather useful, not for truncating email addresses, but giving a browser clues where it can put line breaks into a string if something is too long (e.g. in a table).

    So you could do something like:

    $email =~ s!(\.)!<wbr />$1!g;

    I only mention it because I've found myself doing this a lot..

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?

Re: Shorten email address
by spurperl (Priest) on Jun 10, 2005 at 06:49 UTC
    Some thoughts:

    1. Folding it into a single loop could be more efficient.
    2. What about addresses like supercoderhaxor@np.net ?
      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.
        Or maybe condense both sides by a number of characters... May be more pleasing to the eye super...@some...

        .:| If it can't be fixed .. Don't break it |:.

        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.
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

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.

      The following works fine.
      Sorry, I find Code from God problematic at times. I see a slew of uncommented code, and very short variable names. It also looks difficult to maintain.

      What does it do (or, what do you think it does), and why that instead of something else?

      -QM
      --
      Quantum Mechanics: The dreams stuff is made of

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

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://465444]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (8)
As of 2024-04-18 15:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found