Beefy Boxes and Bandwidth Generously Provided by pair Networks Bob
Syntactic Confectionery Delight
 
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 rifling through the Monastery: (7)
As of 2014-04-17 02:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (437 votes), past polls