用awk改变字符串的大小写

sco*_*fax 10 regex unix awk

我是一个awk新手,所以请耐心等待我.

目标是更改字符串的大小写,使每个单词的第一个字母为大写,其余字母为小写.(为了使示例简单,"word"在此定义为严格的字母字符;所有其他字符都被视为分隔符.)

我学会了一种很好的方法,使用以下awk命令从本网站上的另一篇文章中将每个单词的第一个字母大写:

echo 'abce efgh ijkl mnop' | awk '{for (i=1;i <= NF;i++) {sub(".",substr(toupper($i),1,1),$i)} print}' - > Abcd Efgh Ijkl Mnop

通过使用tr命令执行awk命令,可以轻松完成剩余的小写字母:

echo 'aBcD EfGh ijkl MNOP' | tr [A-Z] [a-z] | awk '{for (i=1;i <= NF;i++) {sub(".",substr(toupper($i),1,1),$i)} print}' - > Abcd Efgh Ijkl Mnop

但是,为了更多地了解awk,我想用一个类似的awk结构将除了第一个字母以外的所有字母改为小写.我使用正则表达式\B[A-Za-z]+匹配单词的所有字母但第一个,而awk命令substr(tolower($i),2)以小写形式提供相同的字母,如下所示:

echo 'ABCD EFGH IJKL MNOP' | awk '{for (i=1;i <= NF;i++) {sub("\B[A-Za-z]+",substr(tolower($i),2),$i)} print}' - > Abcd EFGH IJKL MNOP

请注意,第一个单词正确转换,但其余单词保持不变.我将非常感谢解释为什么剩下的单词没有正确转换以及如何让它们这样做.

And*_*son 8

问题是\B(零宽度非单词边界)似乎只在行的开头匹配,因此$1工作但是$2跟随字段与正则表达式不匹配,因此它们不会被替换并保持大写.不确定为什么\B不匹配除了第一个字段... B应匹配任何单词中的任何位置:

echo 'ABCD EFGH IJKL MNOP' | awk '{for (i=1; i<=NF; ++i) { print match($i, /\B/); }}'
2   # \B matches ABCD at 2nd character as expected
0   # no match for EFGH
0   # no match for IJKL
0   # no match for MNOP
Run Code Online (Sandbox Code Playgroud)

无论如何要实现你的结果(只使用该行的第一个字符),你可以操作$0(整行)而不是使用for循环:

echo 'ABCD EFGH IJKL MNOP' | awk '{print toupper(substr($0,1,1)) tolower(substr($0,2)) }'
Run Code Online (Sandbox Code Playgroud)

或者,如果您仍然希望单独对每个单词进行大写,但awk仅使用:

awk '{for (i=1; i<=NF; ++i) { $i=toupper(substr($i,1,1)) tolower(substr($i,2)); } print }'
Run Code Online (Sandbox Code Playgroud)