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

Vil*_*age 5 csv bash awk tsv

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

sed 's/\t/,/g' file.tsv > file.csv
Run Code Online (Sandbox Code Playgroud)
  • 不需要添加引号.

如何将TSV转换为CSV?

mkl*_*nt0 13

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


总结一下这些选项(有趣的是,它们的表现大致相同):

tr:

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

tr '\t' ',' < file.tsv > file.csv
Run Code Online (Sandbox Code Playgroud)

sed:

sed鉴于输入不包含带引号的字符串(可能包含嵌入\t字符),OP自己的解决方案非常精细.

sed 's/\t/,/g' file.tsv > file.csv
Run Code Online (Sandbox Code Playgroud)

唯一需要注意的是,在某些平台(例如,macOS)上,\t不支持转义序列,因此需要使用文字制表符char.必须使用ANSI quoting($'\t')拼接到命令字符串中:

sed 's/'$'\t''/,/g' file.tsv > file.csv
Run Code Online (Sandbox Code Playgroud)

awk:

需要注意的awkFS- 输入字段分隔符 - 必须设置为\t 显式 - 否则默认行为将剥离前导和尾随选项卡,并仅使用单个选项卡替换多个选项卡的内部跨度,:

awk 'BEGIN { FS="\t"; OFS="," } {$1=$1; print}' file.tsv > file.csv
Run Code Online (Sandbox Code Playgroud)

请注意,简单地分配$1给自身会导致awk使用OFS- 输出字段分隔符重建输入行; 这有效地取代了所有的\t角色.与,chars.print然后只需打印重建线.


强大的awk解决方案:

正如A. Rabus指出的那样,上述解决方案不处理本身,正确包含字符的未加引号的输入字段- 您最终会得到额外的CSV字段.

以下awk解决方案通过"..."按需封装这些字段来修复此问题(请参阅awk上面的非强健解决方案以获得该方法的部分解释):

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
Run Code Online (Sandbox Code Playgroud)
  • "检测包含""但未包含在双引号中的任何字段

  • $i ~ /[,"]/ && $i !~ /^".*"$/ 通过用双引号括起来更新字段

  • 如前所述,更新任何电场使,重建从领域的线与所述",即,gsub("\"", "\"\"", $i)在这种情况下,这相当于有效的TSV - > CSV转换; flag "用于确保每个输入记录至少重建一次.