Bash:转换为小写,但保留每个单词首字母的大小写

Bash: convert to lowercase, BUT preserve the case of the first letter of every word

我反复搜索过这个,但找不到针对这个特定场景的答案。我希望能够将字符串转换为小写,同时保留任何现有的带标题的单词。

例如:

Hello, this is a Titled woRd aND ThIs one is UPPERCASED.

应该变成:

Hello, this is a Titled word and This one is Uppercased.

每个字母都会小写,除了每个单词的第一个字母会保持其大小写。我熟悉改变大小写的常见形式,但不熟悉这种具体形式。不要与 Title case 混淆,因为这不是我在这里要问的。非常感谢任何帮助。

不确定您是否需要纯粹的 bash 解决方案,但使用一些常用的实用程序会让生活更轻松。

使用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.

它简单地遍历所有字段(space-分隔)并分配给每个字段($i)该字段的第一个字母,然后是该字段其余部分的小写副本.

使用 GNU sed(不太便携,但可能更易读):

$ echo 'Hello, this is a Titled woRd aND ThIs one is UPPERCASED.' | \
    sed -r 's/\b(\w)(\w*)/\L/g'
Hello, this is a Titled word and This one is Uppercased.

这匹配一个单词边界 (\b),后跟一个字母(单词字符,\w),然后是零个或多个字母 (\w*)。它用第一个字母 (</code>) 替换它,然后是其余字母 (<code>) 的小写版本 (\L)。

使用 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."

解释:

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."

使用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