Mac OS(Unix环境)下替换CSV文件字符串内逗号分隔符的方法
处理CSV中引号内的逗号问题
我太懂这种烦恼了——CSV里带引号的字段藏着逗号,直接用cut或者简单的sed处理根本没用,因为这些工具完全不懂CSV的引号规则,会把引号里的逗号也当成列分隔符,导致提取数据全乱套。
先说说你之前用的sed 's/" , "/" "/g'为什么没效果:这个命令只替换了引号后面跟着空格逗号空格的特定场景,但你的核心问题是要处理引号内部的逗号(比如"xx, yy, ww"里的逗号),这个sed命令根本碰不到这些逗号,自然解决不了问题。
下面给你几个靠谱的解决方案,都是Mac OS 10.10能直接用的:
方法1:用Python处理(最稳妥,推荐)
Mac自带Python,用官方的csv模块处理完全符合CSV规范,不会出错。写个简单的脚本就行:
import csv # 替换引号内的逗号为空格,你也可以换成其他字符比如分号 with open('myfile.csv', 'r') as infile, open('cleaned.csv', 'w', newline='') as outfile: reader = csv.reader(infile) writer = csv.writer(outfile) # 遍历每一行,清理每个字段里的逗号 for row in reader: cleaned_fields = [field.replace(',', ' ') for field in row] writer.writerow(cleaned_fields)
保存成clean_csv.py,然后在终端执行:
python clean_csv.py
处理完的cleaned.csv里,引号内的逗号都变成了空格,再用cut -d , -f 2,3 cleaned.csv > newfile.csv就能得到正确结果了。
方法2:用awk处理(适合快速终端操作)
如果不想写Python脚本,可以用awk来识别引号状态,只替换引号内的逗号。写个awk脚本process_csv.awk:
BEGIN { FS = ""; OFS = "" } { in_quote = 0 # 标记是否在引号内 for (i=1; i<=NF; i++) { if ($i == "\"") { in_quote = !in_quote # 进入/退出引号状态 print $i } else if (in_quote && $i == ",") { print " " # 把引号内的逗号换成空格 } else { print $i } } print "" # 换行 }
执行命令:
awk -f process_csv.awk myfile.csv > cleaned.csv
方法3:直接提取指定列(不用修改原文件)
其实如果你只是想提取第2、3列,根本不用先替换逗号!直接用Python或者支持CSV规则的awk来提取更高效:
用Python提取:
import csv with open('myfile.csv', 'r') as infile: reader = csv.reader(infile) next(reader) # 跳过表头行 with open('newfile.csv', 'w', newline='') as outfile: writer = csv.writer(outfile) for row in reader: # 提取第2和第3列(注意索引从0开始) writer.writerow([row[1], row[2]])
用GNU awk提取(如果你的Mac装了gawk,比如用brew安装):
gawk 'BEGIN { FPAT = "([^,]+)|(\"[^\"]+\")" } NR>1 { print $2 ", " $3 }' myfile.csv > newfile.csv
FPAT规则会让awk正确识别带引号的字段,不管里面有没有逗号。
内容的提问来源于stack exchange,提问作者jahina97




