我有一些TSV文件需要转换为CSV文件。 BASH中是否有任何解决方案,例如使用awk
来转换这些?我可以像这样使用sed
,但我担心它会犯一些错误:
sed 's/\t/,/g' file.tsv > file.csv
如何将TSV转换为CSV?
答案 0 :(得分:11)
更新:以下解决方案通常不健全 ,尽管它们确实适用于OP的特定用例;请参阅底部,了解基于awk
的强大解决方案。
总结选项(有趣的是,它们的表现大致相同):
<强> TR 强>:
devnull的解决方案(在对问题的评论中提供)是最简单的:
tr '\t' ',' < file.tsv > file.csv
<强> SED 强>:
OP自己的sed
解决方案完全正常,因为输入中不包含带引号的字符串(可能嵌入\t
个字符。):
sed 's/\t/,/g' file.tsv > file.csv
唯一需要注意的是,在某些平台(例如,macOS)上,不支持转义序列\t
,因此文字制表符号为char。必须使用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
解决方案,以获得该方法的部分解释):
awk 'BEGIN { FS="\t"; OFS="," } {
rebuilt=0
for(i=1; i<=NF; ++i) {
if ($i ~ /,/ && $i !~ /^".*"$/) { $i = "\"" $i "\""; rebuilt=1 }
}
if (!rebuilt) { $1=$1 }
print
}' file.tsv > file.csv
$i ~ /,/ && $i !~ /^".*"$/
检测到包含,
并且未用双引号括起来的任何字段
$i = "\"" $i "\""
将字段用双引号括起来更新字段
如前所述,更新任何字段会导致awk
重建来自带有OFS
值的字段的行,即,在这种情况下,,
,相当于有效的TSV - &gt; CSV转换;标记rebuilt
用于确保每个输入记录至少重建一次。
答案 1 :(得分:1)
这也可以通过Perl来实现:
为了将结果传递给新的输出文件,您可以使用以下内容:
perl -wnlp -e 's/\t/,/g;' input_file.tsv > output_file.csv
如果您想编辑该文件,可以调用-i选项:
perl -wnlpi -e 's/\t/,/g;' input_file.txt
如果您发现所处理的内容实际上不是制表符,而是多个空格,您可以使用以下内容用逗号替换每个出现的两个或多个空格:
perl -wnlpi -e 's/\s+/,/g;' input_file
请记住,\s
表示任何空白字符,包括空格,制表符或换行符,不能在替换字符串中使用。
答案 2 :(得分:0)
tr命令:
tr '\t' ',' < file.tsv > file.csv
非常简单,即使在一个非常大的文件(大约10 GB)上也能给出绝对正确且非常快速的结果。
答案 3 :(得分:0)
使用 awk 对我有用
将tsv转换为csv
awk 'BEGIN { FS="\t"; OFS="," } {$1=$1; print}' file.tsv > file.csv
或将csv转换为tsv
awk 'BEGIN { FS=","; OFS="\t" } {$1=$1; print}' file.csv > file.tsv