合并CSV文件:添加而不是合并

时间:2014-07-08 21:31:31

标签: bash shell unix csv merge

所以基本上我想合并几个CSV文件。我使用以下脚本来做到这一点:

paste -d , *.csv > final.txt

然而,这在过去对我有用,但这次它不起作用。它将数据彼此相邻,而不是彼此相邻。例如,包含以下格式的记录的两个文件

CreatedAt   ID
Mon Jul 07 20:43:47 +0000 2014  4.86249E+17
Mon Jul 07 19:58:29 +0000 2014  4.86238E+17
Mon Jul 07 19:42:33 +0000 2014  4.86234E+17

合并时给予

CreatedAt   ID CreatedAt    ID
Mon Jul 07 20:43:47 +0000 2014  4.86249E+17 Mon Jul 07 18:25:53 +0000 2014  4.86215E+17
Mon Jul 07 19:58:29 +0000 2014  4.86238E+17 Mon Jul 07 17:19:18 +0000 2014  4.86198E+17
Mon Jul 07 19:42:33 +0000 2014  4.86234E+17 Mon Jul 07 15:45:13 +0000 2014  4.86174E+17
                                            Mon Jul 07 15:34:13 +0000 2014  4.86176E+17

有谁知道这背后的原因是什么?或者我可以做些什么来强制合并到记录下面?

3 个答案:

答案 0 :(得分:37)

假设所有csv文件具有相同的格式并且都以相同的标头开头, 您可以编写一个小脚本,如下所示只在一个中附加所有文件,只需要一次标题

#!/bin/bash
OutFileName="X.csv"                       # Fix the output name
i=0                                       # Reset a counter
for filename in ./*.csv; do 
 if [ "$filename"  != "$OutFileName" ] ;      # Avoid recursion 
 then 
   if [[ $i -eq 0 ]] ; then 
      head -1  "$filename" >   "$OutFileName" # Copy header if it is the first file
   fi
   tail -n +2  "$filename" >>  "$OutFileName" # Append from the 2nd line each file
   i=$(( $i + 1 ))                            # Increase the counter
 fi
done

注意:

  • head -1head -n 1命令打印文件的第一行(头部)。
  • tail -n +2打印文件的尾部,从第2行开始(+2
  • 测试[ ... ]用于从输入列表中排除输出文件。
  • 每次都会重写输出文件
  • 命令cat a.csv b.csv > X.csv可以简单地用于将a.csv和b csv附加到单个文件中(但是复制标题的2倍)。

paste命令将文件粘贴到另一侧的一侧。如果文件的空格为行,则可以获得上面报告的输出 使用-d ,要求paste command定义以逗号,分隔的字段,但上述报告的文件格式不是这种情况。

cat命令代替连接文件并在标准输出上打印,这意味着它将一个文件写入另一个文件。

有关单个选项的语法,请参阅man headman tail(某些版本允许head -1其他选项head -n 1)...

答案 1 :(得分:0)

非常感谢@wahwahwah。 我使用你的脚本来制作 nautilus-action ,但它只对这些变化有效:

#!/bin/bash

for last; do true; done

OutFileName=$last/RESULT_`date +"%d-%m-%Y"`.csv                       # Fix the output name

i=0                                       # Reset a counter
for filename in "$last/"*".csv"; do

 if [ "$filename" != "$OutFileName" ] ;      # Avoid recursion 
 then 
   if [[ $i -eq 0 ]] ; then 
      head -1  "$filename" > "$OutFileName" # Copy header if it is the first file
   fi
   tail -n +2  "$filename" >> "$OutFileName" # Append from the 2nd line each file
   i=$(( $i + 1 ))                        # Increase the counter
 fi
done

答案 2 :(得分:0)

替代的简单答案,这是Combine_csv.sh:

#!/bin/bash
{ head -n 1 $1 & tail -q -n +2 $*; }

可以像这样combine_csv.sh *pattern*.csv > result.csv

使用