簡體   English   中英

"如何在 BASH 中將制表符分隔值 (TSV) 文件轉換為逗號分隔值 (CSV) 文件?"

[英]How do I convert a tab-separated values (TSV) file to a comma-separated values (CSV) file in BASH?

我有一些 TSV 文件需要轉換為 CSV 文件。 BASH 中是否有任何解決方案,例如使用awk<\/code>來轉換這些? 我可以像這樣使用sed<\/code> ,但我擔心它會犯一些錯誤:

sed 's/\t/,/g' file.tsv > file.csv

更新以下解決方案通常並不健壯,盡管它們確實適用於 OP 的特定用例; 請參閱底部以獲取強大的基於awk的解決方案


總結一下這些選項(有趣的是,它們的表現都差不多):

時間

devnull的解決方案(在對問題的評論中提供)是最簡單的:

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

sed

鑒於輸入不包含帶引號的字符串(可能嵌入\\t字符),OP 自己的sed解決方案非常好:

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 轉換; rebuilt標志用於確保每個輸入記錄至少重建一次

這也可以通過 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代表任何空白字符,包括空格、制表符或換行符,並且不能在替換字符串中使用。

tr 命令:

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

很簡單,即使在一個非常大的文件(大約 10 GB)上也為我提供了絕對正確且非常快速的結果。

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

您可以簡單地在 shell 中使用sed<\/code>的強大功能:

sed -r 's/\t/","/g' file.tsv|sed -r 's/(^|$)/"/g' > file.csv

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM