Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Upper case and chomp

by TechFly (Scribe)
on Feb 09, 2011 at 20:53 UTC ( #887281=perlquestion: print w/ replies, xml ) Need Help??
TechFly has asked for the wisdom of the Perl Monks concerning the following question:

my @listaccountlocked = split("=", $accountlocked); if (chomp($listaccountlocked[1]) eq "True") { system("chuser account_locked='false' $username"); print(`lsuser -a account_locked $username`); } else { print("\nThe account $username is not locked\n\n"); }

In the code above (second line), I would like to use uc() and "TRUE" instead of relying on the OS to always respond in the correct case. Is there a way to do so without adding another variable? Whenever I try to add uc() in I get compilation errors, or I get the result of comping the variable. Probably a very simple thing, but I am at a loss.

Thanks be to the Monks who know.

Comment on Upper case and chomp
Download Code
Re: Upper case and chomp
by wind (Priest) on Feb 09, 2011 at 20:58 UTC
    chomp returns the total number of characters removed, either 1 or 0, so your equality test will always fail. Just split up your efforts:
    my @listaccountlocked = split "=", $accountlocked; chomp($listaccountlocked[1]); if (uc($listaccountlocked[1]) eq "TRUE") {
    - Miller
Re: Upper case and chomp
by kennethk (Monsignor) on Feb 09, 2011 at 21:01 UTC
    As documented in chomp,
    It returns the total number of characters removed from all its arguments.
    This means you are using that incorrectly. Rather than using eq, I would suggest using a regular expression, like

    my @listaccountlocked = split("=", $accountlocked); if ($listaccountlocked[1] =~ /^true$/i) { system("chuser account_locked='false' $username"); print(`lsuser -a account_locked $username`); } else { print("\nThe account $username is not locked\n\n"); }
    where $ will ignore a trailing newline in reporting a match.

      I prefer using uc and a string compare like the OP suggested. I did a quick benchmark, and it looks like it's faster (negligible if no strings match, roughly double the speed if they all match.

      if (uc($listaccountlocked[1]) eq 'TRUE) {

      Trivial benchmark:

      ...roboticus

      When your only tool is a hammer, all problems look like your thumb.

        Another option is string escapes:

        if ("\U$listaccountlocked[1]" eq 'TRUE') {

        I added another sub to your benchmark:

        sub slashU { my $cnt=0; for (@words){ ++$cnt if "\U$_" eq 'ABCB'; } return $cnt; }

        But it didn't fare very well:

        In 4096 words, 16 are 'abcb' Rate slashU uccmp regex slashU 321/s -- -18% -26% uccmp 390/s 21% -- -10% regex 435/s 36% 12% -- In 4096 words, 0 are 'abcb' Rate slashU uccmp regex slashU 328/s -- -17% -25% uccmp 397/s 21% -- -10% regex 439/s 34% 11% -- In 4096 words, 4096 are 'abcb' Rate regex slashU uccmp regex 266/s -- -6% -18% slashU 282/s 6% -- -13% uccmp 325/s 22% 15% --

        Ah well.

        You have not used a fair test: note that my regular expression included the Metacharacters ^ and $. If I reconfigure your tests to consider this factor and swap to:
        sub regex { my $cnt=0; for (@words) { ++$cnt if /^abcb$/i; } return $cnt; }
        I get the output:

        In 4096 words, 16 are 'abcb' Rate uccmp regex uccmp 1192/s -- -5% regex 1255/s 5% -- In 4096 words, 0 are 'abcb' Rate uccmp regex uccmp 1225/s -- -3% regex 1264/s 3% -- In 4096 words, 4096 are 'abcb' Rate regex uccmp regex 970/s -- -23% uccmp 1260/s 30% --

        which obviously compares much better. This still does not consider that the string compare require a chomp which the regular expression does not. Modifying your benchmark to consider this:

        yields the results:
        In 4096 words, 16 are 'abcb' Rate uccmp regex uccmp 812/s -- -32% regex 1197/s 47% -- In 4096 words, 0 are 'abcb' Rate uccmp regex uccmp 861/s -- -31% regex 1255/s 46% -- In 4096 words, 4096 are 'abcb' Rate uccmp regex uccmp 856/s -- -11% regex 964/s 13% --
        which I think clearly favors the regular expression. In addition, if you really wanted to squeeze out performance, you could skip the split in the OP as well: which yields:
        In 4096 words, 16 are 'abcb' Rate uccmp regex uccmp 200/s -- -74% regex 767/s 283% -- In 4096 words, 0 are 'abcb' Rate uccmp regex uccmp 200/s -- -74% regex 756/s 278% -- In 4096 words, 4096 are 'abcb' Rate uccmp regex uccmp 206/s -- -66% regex 603/s 193% --

        Update: As ikegami points out, I failed to localize the arrays to the test routines, so there were a large number of no-ops. Fixing that with the code my @words = @words added where appropriate reduced margins but maintained ordering. I suspect that is just a function of the linear overhead of copying the large arrays. If this is incorrect, I would appreciate insight.

Re: Upper case and chomp
by TechFly (Scribe) on Feb 09, 2011 at 21:09 UTC

    Thanks guys. I did indeed forget that chomp() does not need to be assigned a new variable. I never thought much about using regex either. I am fairly new to that, so it does not come to mind right away.

    Thank you very much for the help.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (3)
As of 2014-09-20 23:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (164 votes), past polls