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

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

Hello Monks! I want to convert my data frame of text into lowercase but I do not want to convert the words with all CAPS letters. For example if have a string like "I am a GIRL" The output of this should be like "i am a GIRL" How can I do this?
  • Comment on Converting a text into lowercase but not the word with all CAPS letters.

Replies are listed 'Best First'.
Re: Converting a text into lowercase but not the word with all CAPS letters.
by tybalt89 (Monsignor) on Jul 09, 2017 at 08:20 UTC

    Taking a guess about your contradictory requirements:

    #!/usr/bin/perl # http://perlmonks.org/?node_id=1194583 use strict; use warnings; while(<DATA>) { s/ \b (?![A-Z]{2,}\b) (\w+) \b /\L$1/gx; print; } __DATA__ I am a GIRL A test WITH Multiple conDITions AND other tests.
Re: Converting a text into lowercase but not the word with all CAPS letters.
by soonix (Canon) on Jul 09, 2017 at 08:09 UTC
    Your specification is incomplete. 'I' is an all-caps word, too, so why do you want it to be lower-cased?
Re: Converting a text into lowercase but not the word with all CAPS letters.
by Marshall (Canon) on Jul 09, 2017 at 12:46 UTC
    Another possibility that could be adapted to fit:
    use warnings; use strict; my $text = "I am a GIRL, a Real GIRL. A test WITH Multiple conDITions +AND other tests."; print map{"$_ "} map{$_ = lc($_) unless (($_ eq uc $_) and length $_ > 1 ); $_ } map{split ' ',$_}$text; __END__ Prints: i am a GIRL, a real GIRL. a test WITH multiple conditions AND other te +sts.
    Converting between upper and lower case ASCII is just flipping a bit (fast). No regex is needed here. length() is also very fast. $_ eq uc $_ should be very fast. This map,map,map stuff is slow, but speeding that up is left to the reader.

    Update: Here is one possibility of many:

    use warnings; use strict; my $text = "I am a GIRL, a Real GIRL. A test WITH Multiple conDITions +AND other tests."; print "".onlyAllcaps ($text); sub onlyAllcaps { my $input = shift; my @words = split ' ',$text; foreach my $word (@words) { $word = lc($word) unless (($word eq uc $word) and length $word> +1 ) } my $output = join " ",@words,"\n"; return $output; } __END__ Prints: i am a GIRL, a real GIRL. a test WITH multiple conditions AND other te +sts.
Re: Converting a text into lowercase but not the word with all CAPS letters.
by derby (Abbot) on Jul 09, 2017 at 11:57 UTC

    This is one of those cases where for readability sake, I would separate the split logic from the case logic. This isn't going to win any perl golf competitions but future maintainers will not try to hunt you down!

    #!/usr/bin/env perl use strict; use warnings; my $input = "I am a GIRL"; my $output = []; # split input by non-words ... if you need to keep non-word # characters then you'll need a different regex foreach my $word ( split( /\W+/, $input ) ) { # if the word is all upper case and it's not a single letter if( $word =~ /^\p{Uppercase}+$/ && length( $word ) > 1 ) { push( @$output, $word ); } else { push( @$output, lc $word ); } } print join( ' ', @$output ), "\n";

    -derby

    update: Fix regex from /\p{Lu}+/ to /^\p{Uppercase}+$/