按列值拆分CSV,并保留标题

时间:2018-07-27 16:21:49

标签: csv awk

这个问题已经被问过很多次了,但是我根本无法正确地实施解决方案。我有一个名为2017-01.csv的大型csv,带有日期列(这是文件中的第二列),并且按日期拆分文件。原始文件如下所示:

 date
 2017-01-01
 2017-01-01
 2017-01-01
 2017-01-02
 2017-01-02
 2017-01-02

分裂之后,2017-01-01.csv看起来像

2017-01-01
2017-01-01
2017-01-01

和2017-01-02.csv看起来像

2017-01-02
2017-01-02
2017-01-02

我正在使用的代码是

awk -F ',' '{print > (""$2".csv")}' 2017.csv

一切正常,但我需要保留标题行。所以我尝试了

awk -F ',' 'NR==1; NR > 1{print > (""$2".csv")}' 2017-01.csv

但是没有标题行,我仍然得到相同的结果。我究竟做错了什么?我在Stackoverflow上阅读了许多类似问题的答案,但我只是不明白他们在做什么。

我想要这个:

2017-01-01.csv应该看起来像

date
2017-01-01
2017-01-01
2017-01-01

2017-01-02.csv应该看起来像

date
2017-01-02
2017-01-02
2017-01-02

2 个答案:

答案 0 :(得分:3)

awk -F, '
FNR==1{hdr=$2}
 FNR > 1{
   if (! hdrPrinted[$2]){
      print hdr > (""$2".csv")
      hdrPrinted[$2]=$2
  }
  print $1, $2, $3> (""$2".csv")
}' 2017-01.csv

并且作为1班轮

awk -F, ' FNR==1{hdr=$2} FNR > 1{ if (! hdrPrinted[$2]){ print hdr > (""$2".csv"); hdrPrinted[$2]=$2; } print $1, $2, $3> (""$2".csv") }' 2017-01.csv

产生输出

cat 2017\-01\-01.csv
date
  2017-01-01
  2017-01-01
  2017-01-01

cat 2017\-01\-02.csv
date
  2017-01-02
  2017-01-02
  2017-01-02

请注意,FNR表示FileNumber(of)Record,因此每次打开一个新文件时,FNR都将重置为1。这可能会在某些特定情况下引起问题,但通常我认为是更好的方法是,允许您在cmd行上列出多个文件,并在一个进程中全部处理。

-----------------

根据下面的合理注释,这是防弹版本,如果cmd行上列出了20个以上的文件,则该版本应能应对。

我没有一种简单的方法来进行测试,因此欢迎您提供反馈。

并且根据下面的评论,它仍然需要做一些工作,我现在没有时间。寻找星期六下午的更新。

awk -F, ' FNR==1{hdr=$2}  FNR > 1{
      # length() assumes newish gawk version
      if ( length(openFiles) > 20) {
             # close the first/next file in the array
             close(openFiles[++j]".csv")
             openFiles[j]=""
      }
      if (! ($2 in openFiles) ) {
             # put the filename into the openFiles array (just once)
            openFiles[++i]=$2
            }    if (! hdrPrinted[$2]){
   print hdr > (""$2".csv")
  hdrPrinted[$2]=$2   }   print $1, $2, $3> (""$2".csv") 2017-01.csv

IHTH

埃德·莫顿(Ed Morton)编辑:

awk -F, '
FNR==1 { hdr=$0; next}
{
    out = $2 ".csv"
    if (!seen[out]++) {
        print hdr > out
    }
    print >> out
    close(out)
}
' file

答案 1 :(得分:0)

以下内容在包含多列且第二列设置为日期的csv上进行了测试:

awk -F',' 'prev!=$2{close(prev".csv");print "date" > ($2".csv")}{print $2 > ($2".csv");prev=$2}' Input_file

hth