首页 > 解决方案 > 按列值拆分 CSV,并保留标题

问题描述

这已经被问过很多次了,但我根本无法正确实施解决方案。我有一个名为 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

标签: csvawk

解决方案


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

埃德莫顿编辑:

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

推荐阅读