http://www.perlmonks.org?node_id=150558

nop has asked for the wisdom of the Perl Monks concerning the following question:

I want to capitalize the first and last letter of a string.
This works but strikes me as excessive:
$user =~ s/^(.)(.*)(.)$/\u$1\L$2\E\u$3/; # capitalize 1st and last + letter
Is there something preferable?

(This title of this posting is a joke, I know there isn't  uclast)

nop

Replies are listed 'Best First'.
Re: ucfirst(uclast(lc($user))) ?
by Juerd (Abbot) on Mar 09, 2002 at 13:52 UTC

    (This title of this posting is a joke, I know there isn't uclast )

    sub uclast ($) { my ($foo) = @_; $foo =~ s/(.)$/uc $1/e; return $foo; }

    Now there is :)

    44696420796F7520732F2F2F65206F
    7220756E7061636B3F202F6D736720
    6D6521203A29202D2D204A75657264
    

      /e is a bit excessive here, isn't it? :) Also, you may want to only match against (\w) instead of (.). No reason to try to uppercase a funny character!

      sub uclast ($) { my $foo = shift; $foo =~ s/(\w)$/\u$1/; return $foo; }

        /e is a bit excessive here, isn't it? :)

        No, I don't think it is. I dislike using interpolation when there's only a single variable being used and no literal text. Great when golfing, but just annoying line noise otherwise.

        Also, you may want to only match against (\w) instead of (.).

        Good point. I thought \w was not affected by using locales, but it is.

        44696420796F7520732F2F2F65206F
        7220756E7061636B3F202F6D736720
        6D6521203A29202D2D204A75657264
        

      Nice!

      ..Guv

      Update: totally baffled as to why complimenting Juerd's solution would possibly garner me a --. Feel free to /msg me to 'splain the error of my ways.

        I learned this when I posted a "your welcome" post...

        Redundant posts normally get -- by monks that wish to keep the signal to noise level down, nothing personal I think. I myself now sometimes -- posts that offer the same solutions offered by previous posts hours ago. How many "use CGI.pm, use strict, use warnings" posts do you need ? ++ the first few and -- the "me too" posts.

        In any event, your update seems to have awaken the human side in some :)

        Tiago
Re: ucfirst(uclast(lc($user))) ?
by theguvnor (Chaplain) on Mar 09, 2002 at 13:47 UTC

    An alternative is:

    $user = reverse(ucfirst(reverse(ucfirst(lc $user))));

    I'm NOT saying this is less excessive :^)

    ..Guv

      While it may be the least readable solution of the bunch (IMHO, thanks to the parens; YMMV... ), adapted to work as a uclast function, it's the speediest of the bunch ...

      # Output reformatted for readability :) Benchmark: running juerd, seattlejohn, theguvnor, each for at least 5 CPU seconds... juerd: 6 wallclock secs ( 5.18 usr + 0.00 sys = 5.18 CPU) @ 20926.21/s (n=108335) seattlejohn: 6 wallclock secs ( 5.36 usr + 0.00 sys = 5.36 CPU) @ 47568.95/s (n=254922) theguvnor: 5 wallclock secs ( 5.33 usr + 0.00 sys = 5.33 CPU) @ 103021.21/s (n=548897) Rate juerd seattlejohn theguvnor juerd 20926/s -- -56% -80% seattlejohn 47569/s 127% -- -54% theguvnor 103021/s 392% 117% --

        Sweet - I have now become a subroutine! And I'm reasonably fast!! :) Kanji++

        ..Guv

Re: ucfirst(uclast(lc($user))) ?
by seattlejohn (Deacon) on Mar 10, 2002 at 04:48 UTC
    Here's a slightly sneaky solution that I happen to find quite readable:

    substr($thing,-1,1) =~ tr/a-z/A-Z/;

    The trick is knowing that substr can be used as an lvalue...

Re (tilly) 1: ucfirst(uclast(lc($user))) ?
by tilly (Archbishop) on Mar 10, 2002 at 01:41 UTC
    Define "works".
    my $user = "Hello There, Trusting Programmer"; $user =~ s/^(.)(.*)(.)$/\u$1\L$2\E\u$3/; print $user;
    At the least you need a /s modifier...