我有一些 TSV 文件需要转换为 CSV 文件。 BASH 中是否有任何解决方案,例如使用 awk
来转换这些?我可以像这样使用 sed
,但我担心它会出错:
sed 's/\t/,/g' file.tsv > file.csv
- 无需添加引号。
如何将 TSV 转换为 CSV?
最佳答案
更新:以下解决方案不是通常可靠,尽管它们确实适用于 OP 的特定用例;请参阅底部以了解基于awk
的解决方案。
总结这些选项(有趣的是,它们的表现都差不多):
:
devnull的解决方案(在对问题的评论中提供)是最简单的:
tr '\t' ',' < file.tsv > file.csv
sed:
OP 自己的 sed
解决方案非常好,因为输入不包含带引号的字符串(可能嵌入 \t
字符。):
sed 's/\t/,/g' file.tsv > file.csv
唯一需要注意的是,在某些平台(例如 macOS)上,不支持转义序列 \t
,因此只能使用文字制表符。必须使用 ANSI 引号 ($'\t'
) 拼接到命令字符串中:
sed 's/'$'\t''/,/g' file.tsv > file.csv
awk:
awk
的警告是 FS
- 输入字段分隔符 - 必须设置为 \t
显式 - 默认行为将去除前导和尾随选项卡,并仅用单个 ,
替换多个选项卡的内部跨度:
awk 'BEGIN { FS="\t"; OFS="," } {$1=$1; print}' file.tsv > file.csv
请注意,简单地将 $1
分配给自身会导致 awk
使用 OFS
重建输入行 - 输出字段分隔符;这有效地替换了所有 \t
字符。带有 ,
字符。 print
然后简单地打印重建的行。
健壮的awk
解决方案:
作为A. Rabus指出,上述解决方案无法正确处理本身包含 ,
字符的未加引号的输入字段 - 您最终会得到额外的 CSV 字段。
下面的 awk
解决方案解决了这个问题,方法是根据需要将这些字段包含在 "..."
中(参见非健壮的 awk
上面的解决方案是对该方法的部分解释)。
如果此类字段还嵌入了 "
字符。,这些字符将转义为 ""
,符合 RFC 4180。谢谢,Wyatt Israel。
awk 'BEGIN { FS="\t"; OFS="," } {
rebuilt=0
for(i=1; i<=NF; ++i) {
if ($i ~ /,/ && $i !~ /^".*"$/) {
gsub("\"", "\"\"", $i)
$i = "\"" $i "\""
rebuilt=1
}
}
if (!rebuilt) { $1=$1 }
print
}' file.tsv > file.csv
$i ~/[,"]/&& $i !~/^".*"$/
检测包含,
和/的任何字段或"
并且尚未用双引号引起来gsub("\"", "\"\"", $i)
转义嵌入的"
字符。将它们加倍$i = "\""$i "\""
通过将结果括在双引号中来更新结果如前所述,更新任何字段都会导致
awk
使用OFS
值重建来自字段的行,即本例中的,
,相当于有效的 TSV -> CSV 转换; flagrebuilt
用于确保每条输入记录至少重建一次。
关于bash - 如何在 BASH 中将制表符分隔值 (TSV) 文件转换为逗号分隔值 (CSV) 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22419979/