如何在Bash中用sed替换CSV分隔符但保留字符串内的逗号
替换CSV分隔符但保留字段内逗号的Bash解决方案
需求与场景
要把CSV文件中的分隔符逗号(,)替换为分号(;),但必须保留双引号包裹的字段内部的逗号——比如示例里"User,Super"中的逗号不能被替换。
测试数据
当前test.csv内容:
"001","User,Super","04/04/2024"
期望结果
"001";"User,Super";"04/04/2024"
失败尝试
之前使用的sed命令逻辑错误,无法区分引号内外的逗号,且误用HTML实体匹配引号,导致替换失效:
sed -r 's/("*,*")|,/\;/g' test.csv
有效解决方案
方案1:GNU sed分支正则
通过sed的循环匹配逻辑,仅替换不在双引号内的逗号:
sed -E ':a;s/^(([^"]|"[^"]*")*),/\1;/;ta' test.csv
逻辑说明:
:a定义循环标签,用于重复处理剩余内容- 正则
^(([^"]|"[^"]*")*)匹配所有未进入引号、或已经从引号内退出的内容 - 找到该内容后的第一个逗号,替换为分号
ta如果替换成功,跳回标签a继续处理,直到所有分隔符逗号都被替换
方案2:GNU awk字段匹配
利用awk的FPAT定义CSV字段规则,精准识别字段后用分号拼接输出:
awk 'BEGIN{FPAT="([^,]+)|(\"[^\"]+\")"}{for(i=1;i<=NF;i++){printf "%s%s", $i, (i<NF)?";":ORS}}' test.csv
逻辑说明:
FPAT指定CSV字段的两种合法模式:要么是不含逗号的纯文本,要么是双引号包裹的任意内容(允许内部包含逗号)- 遍历每个字段,用分号作为新的字段分隔符输出,自动跳过字段内部的逗号
内容的提问来源于stack exchange,提问作者Lorenzo Cesana
相关产品推荐
相关产品推荐

