如何在BASH中将制表符分隔值(TSV)文件转换为逗号分隔值(CSV)文件?

如何在BASH中将制表符分隔值(TSV)文件转换为逗号分隔值(CSV)文件?,bash,csv,awk,tsv,Bash,Csv,Awk,Tsv,我有一些TSV文件需要转换成CSV文件。BASH中是否有任何解决方案,例如使用awk,来转换这些?我可以像这样使用sed,但我担心它会出错: sed 's/\t/,/g' file.tsv > file.csv 不需要添加引号 如何将TSV转换为CSV?更新:以下解决方案通常不健壮,尽管它们在OP的特定用例中有效;请参阅底部部分,了解基于强大的awk的解决方案 总结一下这些选项(有趣的是,它们的性能几乎相同): tr: 的解决方案(在对问题的评论中提供)是最简单的: tr '\t'

我有一些TSV文件需要转换成CSV文件。BASH中是否有任何解决方案,例如使用
awk
,来转换这些?我可以像这样使用
sed
,但我担心它会出错:

sed 's/\t/,/g' file.tsv > file.csv
  • 不需要添加引号

如何将TSV转换为CSV?

更新:以下解决方案通常不健壮,尽管它们在OP的特定用例中有效;请参阅底部部分,了解基于强大的
awk
的解决方案


总结一下这些选项(有趣的是,它们的性能几乎相同):

tr

的解决方案(在对问题的评论中提供)是最简单的:

tr '\t' ',' < file.tsv > file.csv
唯一需要注意的是,在某些平台(如macOS)上,不支持转义序列
\t
,因此需要使用文本制表符。必须使用ANSI引号(
$'\t'
)将其拼接到命令字符串中:

awk

awk
的警告是,
FS
——输入字段分隔符——必须明确设置为
\t
——否则默认行为将去除前导和尾随选项卡,并用一个
替换多个选项卡的内部跨距:

awk 'BEGIN { FS="\t"; OFS="," } {$1=$1; print}' file.tsv > file.csv
请注意,简单地将
$1
分配给自身会导致
awk
使用
OFS
-输出字段分隔符来重建输入行;这将有效地替换所有
\t
字符。使用
字符<代码>打印然后只打印重建的行


稳健
awk
解决方案

如前所述,上述解决方案无法正确处理本身包含
字符的无引号输入字段-您将得到额外的CSV字段

以下
awk
解决方案通过将这些字段按需封装在
“…”
中解决了这一问题(有关方法的部分解释,请参阅上文的非稳健
awk
解决方案)

如果这些字段还嵌入了
字符,则这些字符将按照.Thank.的规定转义为

awk'BEGIN{FS=“\t”;OFS=“,”}{
重建=0
对于(i=1;itr命令:

tr '\t' ',' < file.tsv > file.csv
tr'\t'','file.csv

非常简单,即使在一个非常大的文件(大约10 GB)上,也能为我提供绝对正确且非常快速的结果。

这也可以通过Perl实现:

为了将结果传输到新的输出文件,可以使用以下命令:
perl-wnlp-e's/\t/,/g;'input_file.tsv>output_file.csv

如果要就地编辑文件,可以调用-i选项:
perl-wnlpi-e's/\t/,/g;'input\u file.txt

如果您偶然发现所处理的不是制表符,而是多个空格,那么您可以使用以下命令将两个或多个空格中的每一个替换为逗号:
perl-wnlpi-e's/\s+/,/g;'input\u文件


请记住,
\s
表示任何空格字符,包括空格、制表符或换行符,不能在替换字符串中使用。

使用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

如果要忽略带引号的字符串中的制表符/逗号,这就有点复杂了。原始文件不使用带引号的字符串,输出文件也不需要添加这些字符串。@Village
tr
将是上述工作的正确工具,但您担心sed会犯什么样的错误?能否更新您的问题以显示您认为sed可能无法正确处理的一些示例输入?wrt
awk的警告是,FS(输入字段分隔符)必须显式地设置为\t
——这对awk的警告并不比对
tr
sed
的警告多。在所有3种工具中,您都需要指定输入字段分隔符以及要转换的内容如果你不这样做,那么显然你就不会得到你想要的行为。@EdMorton:由于
\t
awk
默认视为输入字段分隔符的字符之一,人们可能会认为在这里设置输入字段分隔符是不必要的——这是我指出的错误,因此注意事项。至于
tr
sed
:输入字段分隔符的概念不适用。当我说
input field separator
时,我的意思是
将输入分隔为字段(值)
的字符,适用于所述的输入格式(
制表符分隔值
),而不是任何特定的工具。我只是认为,对于awk来说,告诉它如何按照期望的方式运行比为其他工具指定它更像是一个警告——这在所有3个工具中都是完全相同的概念,如果你不这样做,那么你将无法获得期望的行为。无论如何,
tr
是适合该工作的工具,正如所述,因此它是正确的可能是一个没有实际意义的问题。您也可以使用vim。只需使用以下从命令模式进行搜索和替换:
:%s/\t/,/g
,这样您就可以立即查看结果,并在需要时按一下按钮(u)将其撤消。如果您已经在使用Perl,还可以使用
tr '\t' ',' < file.tsv > file.csv
awk 'BEGIN { FS="\t"; OFS="," } {$1=$1; print}' file.tsv > file.csv
awk 'BEGIN { FS=","; OFS="\t" } {$1=$1; print}' file.csv > file.tsv