Reputation:
I searched for this repeatedly but I couldn't find an answer for this specific scenario. I'd like to be able to convert a string to lowercase while also preserving any existing titled words.
For example:
Hello, this is a Titled woRd aND ThIs one is UPPERCASED.
should become:
Hello, this is a Titled word and This one is Uppercased.
Every letter would be lowercased, except the first letter of each word would keep its case. I'm familiar with the common forms of changing case but not something this specific. Not to be confused with Title case, as that is not what I'm asking here. Any help is much appreciated.
Upvotes: 1
Views: 725
Reputation: 12867
Using GNU awk:
awk '{ for (i=1;i<=NF;i++) { printf "%s",substr($i,1,1);for(j=2;j<=length($i);j++) { printf "%s",tolower(substr($i,j,1))} printf "%s"," " } }' <<< "Hello, this is a Titled woRd aND ThIs one is UPPERCASED."
Explanation:
awk '{
for (i=1;i<=NF;i++) { # Loop on each word
printf "%s",substr($i,1,1); # Print the first letter in the word
for(j=2;j<=length($i);j++) {
printf "%s",tolower(substr($i,j,1)) # Loop on the rest of the letters in the word and print in lower case
}
printf "%s"," " # Print a space
}
}' <<< "Hello, this is a Titled woRd aND ThIs one is UPPERCASED."
Using bash:
for var in $(echo "Hello, this is a Titled woRd aND ThIs one is UPPERCASED.");
do
printf "%s" ${var:0:1}; # Print the first letter of the word
var1=${var:1}; # Read the rest of the word into var1
printf "%s " "${var1,,[$var1]}"; # Convert vars into lowercase and print
done
Upvotes: 2
Reputation: 181715
Not sure if you need a pure bash
solution, but using some commonly available utilities makes life easier.
Using awk
:
$ echo 'Hello, this is a Titled woRd aND ThIs one is UPPERCASED.' | \
awk '{for(i=1;i<=NF;i++){$i=substr($i,1,1)tolower(substr($i,2))}}1'
Hello, this is a Titled word and This one is Uppercased.
It simply iterates over all fields (space-separated) and assigns to each field ($i
) the first letter of that field, followed by a downcased copy of the remainder of the field.
Using GNU sed
(less portable, but perhaps more readable):
$ echo 'Hello, this is a Titled woRd aND ThIs one is UPPERCASED.' | \
sed -r 's/\b(\w)(\w*)/\1\L\2/g'
Hello, this is a Titled word and This one is Uppercased.
This matches a word boundary (\b
) followed by a letter (word character, \w
) and then zero or more letters (\w*
). It replaces this by the first letter (\1
), followed by the lowercased version (\L
) of the remaining letters (\2
).
Upvotes: 3