如何用awk实现CSV带引号字段中每个单词首字母大写?
用awk实现CSV字段单词首字母大写
问题描述
需要处理CSV文件,让带双引号的字段和普通字段内的每个单词首字母大写,保留原CSV的格式(包括引号和内部逗号)。
输入示例:
8,7,martin sanders, Executive director,, 9,8,bred simons,"manager, second career services",, 10,9,Kely bricks,ceo,,
期望输出:
8,7,Martin Sanders, Executive Director,, 9,8,Bred Simons,"Manager, Second Career Services",, 10,9,Kely Bricks,Ceo,,
原代码问题分析
你之前的代码存在几个关键错误:
- 同时使用
FS="\""和FPAT:这两个选项互斥,FPAT按内容匹配字段,FS按分隔符拆分,同时设置会导致字段识别逻辑混乱。 - 带引号字段的处理逻辑错误:
toupper(substr($i,2,len-2))""tolower(substr($i,2,len))会把字段内容先全大写再拼接全小写,完全不符合“首字母大写”的需求。 - 循环内直接
print $i:会导致每个字段单独输出,无法拼接成完整的CSV行。
解决方案
使用gawk的FPAT正确识别CSV字段,配合自定义函数实现单词首字母大写:
gawk -v FPAT='("[^"]+"|[^,]+)' ' function capitalize(str) { # 处理每个单词首字母大写,其余小写 gsub(/\y[a-z]/, toupper(substr(str, RSTART, RLENGTH)), str) return str } { for (i=1; i<=NF; i++) { if ($i ~ /^"/) { # 处理带引号的字段:去掉引号→处理→加回引号 content = substr($i, 2, length($i)-2) $i = "\"" capitalize(content) "\"" } else { # 处理普通字段 $i = capitalize($i) } } # 用OFS拼接字段输出整行 print } ' input.csv
FPAT原理说明
FPAT是gawk专属特性,用于定义字段的匹配规则,替代传统的分隔符(FS)拆分方式:
- 对于CSV场景,
FPAT='("[^"]+"|[^,]+)'表示:"[^"]+":匹配被双引号包裹的内容(内部可包含逗号)[^,]+:匹配不包含逗号的普通内容
- awk会根据这个规则自动扫描每一行,把符合规则的内容识别为单独字段,完美处理带内部逗号的引号字段。
内容的提问来源于stack exchange,提问作者Volodymyr S
相关产品推荐
相关产品推荐

