如何用sed有条件替换文本?实现字段值标题化并保留字段名
问题描述
现有员工信息文件内容如下:
EMPLOYEE FIRST NAME: JOHN LAST NAME: DOE POSITION: ACCOUNT MANAGER EMPLOYEE FIRST NAME: BIG LAST NAME: BOSS POSITION: CEO
需求如下:
- 将字段值转换为标题大小写(单词首字母大写其余小写,多词则每个词首字母大写)
- 保留字段名(
FIRST NAME、LAST NAME、POSITION)的全大写格式 - 保留原有缩进对齐
- 全大写缩写(如
CEO)保持原样不变
此前使用的sed命令误修改了字段名的大小写,得到错误结果:
EMPLOYEE First Name: John Last Name: Doe Position: Account Manager EMPLOYEE First Name: Big Last Name: Boss Position: Ceo
询问能否用sed实现正确需求,若可行该如何操作。
解决方案
完全可以用sed实现,核心是仅对冒号后的字段值部分处理,避免影响字段名,同时添加逻辑保留全大写缩写。
最终命令
sed -E '/^\s*(FIRST NAME|LAST NAME|POSITION):/ { # 拆分字段名与值,暂存字段名 s/^(\s*(FIRST NAME|LAST NAME|POSITION):\s*)(.*)/\1/ h # 提取字段值单独处理 s/^.*:\s*// # 转换为标题大小写 s/\b([A-Za-z])([A-Za-z]*)\b/\U\1\L\2/g # 恢复长度≤3的全大写缩写(如Ceo → CEO) s/\b([A-Z][a-z]{1,2})\b/\U&/g # 合并字段名与处理后的值 G s/(.*)\n(.*:\s*).*/\2\1/ }' employees.list
命令解析
- 目标行匹配:
/^\s*(FIRST NAME|LAST NAME|POSITION):/精准匹配包含目标字段的行,避免误处理其他行 - 拆分与暂存:
- 用
s/^(\s*(FIRST NAME|LAST NAME|POSITION):\s*)(.*)/\1/保留字段名(含缩进和冒号)到模式空间 h将字段名存入hold空间临时保存
- 用
- 字段值处理:
s/^.*:\s*//删除模式空间内的字段名,仅保留字段值s/\b([A-Za-z])([A-Za-z]*)\b/\U\1\L\2/g把每个词转换为标题大小写:首字母大写,其余字母小写s/\b([A-Z][a-z]{1,2})\b/\U&/g将长度为2或3的标题大小写词转回全大写,恢复CEO这类缩写的原样
- 结果合并:
G将hold空间的字段名追加到模式空间s/(.*)\n(.*:\s*).*/\2\1/重新组合字段名与处理后的字段值,还原原有缩进格式
执行结果
运行命令后得到符合需求的输出:
EMPLOYEE FIRST NAME: John LAST NAME: Doe POSITION: Account Manager EMPLOYEE FIRST NAME: Big LAST NAME: Boss POSITION: CEO
如果不需要保留全大写缩写(所有值严格按标题大小写处理),只需去掉恢复缩写的那一行命令即可。
内容的提问来源于stack exchange,提问作者mike
相关产品推荐
相关产品推荐

