如何在 OSX 中使用 sed 将每个单词的首字母大写
How to capitalize first letter of every word using sed in OSX
我尝试使用以下 sed 命令将字符串中每个单词的首字母大写,但它不起作用:
echo "my string" | sed 's/\b\(.\)/\u/g'
输出:
my string
我做错了什么?
谢谢
尝试:
echo "my string" | sed -r 's/\b(.)/\u/g'
已解决此问题:Uppercasing First Letter of Words Using SED
我在 GNU sed 中得到了正确的行为,但在 OS X 附带的标准 BSD sed 中却没有。我认为 \u "regular expression" 是 GNU 的东西。 "port install gsed"怎么样?
编辑:如果你真的想要使用 BSD sed,我不推荐使用它(因为命令变得非常丑陋),那么你可以执行以下操作:
sed -E "s:([^[:alnum:]_]|^)a:A:g; s:([^[:alnum:]_]|^)b:B:g; s:([^[:alnum:]_]|^)c:C:g; s:([^[:alnum:]_]|^)d:D:g; s:([^[:alnum:]_]|^)e:E:g; s:([^[:alnum:]_]|^)f:F:g; s:([^[:alnum:]_]|^)g:G:g; s:([^[:alnum:]_]|^)h:H:g; s:([^[:alnum:]_]|^)i:I:g; s:([^[:alnum:]_]|^)j:J:g; s:([^[:alnum:]_]|^)k:K:g; s:([^[:alnum:]_]|^)l:L:g; s:([^[:alnum:]_]|^)m:M:g; s:([^[:alnum:]_]|^)n:N:g; s:([^[:alnum:]_]|^)o:O:g; s:([^[:alnum:]_]|^)p:P:g; s:([^[:alnum:]_]|^)q:Q:g; s:([^[:alnum:]_]|^)r:R:g; s:([^[:alnum:]_]|^)s:S:g; s:([^[:alnum:]_]|^)t:T:g; s:([^[:alnum:]_]|^)u:U:g; s:([^[:alnum:]_]|^)v:V:g; s:([^[:alnum:]_]|^)w:W:g; s:([^[:alnum:]_]|^)x:X:g; s:([^[:alnum:]_]|^)y:Y:g; s:([^[:alnum:]_]|^)z:Z:g;"
鉴于您的示例输入,这将适用于任何 awk:
$ echo 'my string' | awk '{for (i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) substr($i,2)} 1'
My String
如果这不能满足您的真正需求,请编辑您的问题以显示一些更具代表性的示例输入和预期输出。
这是一个适用于 OSX 的 sed 解决方案:
echo 'my string
ANOTHER STRING
tHiRd StRiNg' | sed -En '
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
:loop
h
s/^(.*[^a-zA-Z0-9])?([a-z]).*$//
t next
b end
:next
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
G
s/^(.+)\n(.*[^a-zA-Z0-9])?[a-z](.*)$//
t loop
:end
p
'
Output:
My String
Another String
Third String
sed 命令的工作原理如下:
- sed输入一行,第一个y命令将所有大写字母转换为小写。
- 从:loop到t loop的命令形成一个循环,执行一次for
当前行中的每个单词,每个单词的第一个字母大写。
- 当当前行没有大写单词时,p命令打印该行,sed输入下一行。
循环的工作原理如下:
- h 命令将行保存为保留状态
space.
- 第一个s命令查找第一个字母
非大写单词。如果找到这样的词,s 命令保存
它的第一个字母到模式 space,并且 t 命令分支到
:next 标签。如果没有找到这样的词,说明
没有更多的单词需要大写,b命令被执行
相反,分支到 :end 标签打印并完成
当前行的处理。
- 如果找到需要大写的单词,则从
:next 标签,y 命令将现在模式 space 中的第一个字母从小写转换为大写。
- G命令追加当前的非转换版本
从保持点 space 到模式末尾的行 space.
- 第二个 s 命令重建当前行,用大写版本替换当前正在处理的单词的第一个字母。
- t 命令分支到 :loop 标签寻找下一个词
需要大写。
执行速度测试显示,当前的 sed 方法的执行速度与 Ed Morton 提交的 awk 解决方案的执行速度大致相同。
我尝试使用以下 sed 命令将字符串中每个单词的首字母大写,但它不起作用:
echo "my string" | sed 's/\b\(.\)/\u/g'
输出:
my string
我做错了什么?
谢谢
尝试:
echo "my string" | sed -r 's/\b(.)/\u/g'
已解决此问题:Uppercasing First Letter of Words Using SED
我在 GNU sed 中得到了正确的行为,但在 OS X 附带的标准 BSD sed 中却没有。我认为 \u "regular expression" 是 GNU 的东西。 "port install gsed"怎么样?
编辑:如果你真的想要使用 BSD sed,我不推荐使用它(因为命令变得非常丑陋),那么你可以执行以下操作:
sed -E "s:([^[:alnum:]_]|^)a:A:g; s:([^[:alnum:]_]|^)b:B:g; s:([^[:alnum:]_]|^)c:C:g; s:([^[:alnum:]_]|^)d:D:g; s:([^[:alnum:]_]|^)e:E:g; s:([^[:alnum:]_]|^)f:F:g; s:([^[:alnum:]_]|^)g:G:g; s:([^[:alnum:]_]|^)h:H:g; s:([^[:alnum:]_]|^)i:I:g; s:([^[:alnum:]_]|^)j:J:g; s:([^[:alnum:]_]|^)k:K:g; s:([^[:alnum:]_]|^)l:L:g; s:([^[:alnum:]_]|^)m:M:g; s:([^[:alnum:]_]|^)n:N:g; s:([^[:alnum:]_]|^)o:O:g; s:([^[:alnum:]_]|^)p:P:g; s:([^[:alnum:]_]|^)q:Q:g; s:([^[:alnum:]_]|^)r:R:g; s:([^[:alnum:]_]|^)s:S:g; s:([^[:alnum:]_]|^)t:T:g; s:([^[:alnum:]_]|^)u:U:g; s:([^[:alnum:]_]|^)v:V:g; s:([^[:alnum:]_]|^)w:W:g; s:([^[:alnum:]_]|^)x:X:g; s:([^[:alnum:]_]|^)y:Y:g; s:([^[:alnum:]_]|^)z:Z:g;"
鉴于您的示例输入,这将适用于任何 awk:
$ echo 'my string' | awk '{for (i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) substr($i,2)} 1'
My String
如果这不能满足您的真正需求,请编辑您的问题以显示一些更具代表性的示例输入和预期输出。
这是一个适用于 OSX 的 sed 解决方案:
echo 'my string
ANOTHER STRING
tHiRd StRiNg' | sed -En '
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
:loop
h
s/^(.*[^a-zA-Z0-9])?([a-z]).*$//
t next
b end
:next
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
G
s/^(.+)\n(.*[^a-zA-Z0-9])?[a-z](.*)$//
t loop
:end
p
'
Output:
My String
Another String
Third String
sed 命令的工作原理如下:
- sed输入一行,第一个y命令将所有大写字母转换为小写。
- 从:loop到t loop的命令形成一个循环,执行一次for 当前行中的每个单词,每个单词的第一个字母大写。
- 当当前行没有大写单词时,p命令打印该行,sed输入下一行。
循环的工作原理如下:
- h 命令将行保存为保留状态 space.
- 第一个s命令查找第一个字母 非大写单词。如果找到这样的词,s 命令保存 它的第一个字母到模式 space,并且 t 命令分支到 :next 标签。如果没有找到这样的词,说明 没有更多的单词需要大写,b命令被执行 相反,分支到 :end 标签打印并完成 当前行的处理。
- 如果找到需要大写的单词,则从 :next 标签,y 命令将现在模式 space 中的第一个字母从小写转换为大写。
- G命令追加当前的非转换版本 从保持点 space 到模式末尾的行 space.
- 第二个 s 命令重建当前行,用大写版本替换当前正在处理的单词的第一个字母。
- t 命令分支到 :loop 标签寻找下一个词 需要大写。
执行速度测试显示,当前的 sed 方法的执行速度与 Ed Morton 提交的 awk 解决方案的执行速度大致相同。