【问题标题】:Split this csv/xls into separate files based on two columns?根据两列将此 csv/xls 拆分为单独的文件?
【发布时间】:2011-10-05 08:06:25
【问题描述】:

我有一个包含这些列的 35 MB Excel 文件:

Index, Name, Year, AgeGroup1, AgeGroup2, AgeGroup3 [...]
1, Sweden, 1950, 20, 25, 27
2, Norway, 1950, 22, 27, 28
2, Sweden, 1951, 24, 24, 22

我想根据“名称”列将文件拆分为多个 csv 文件(最好还根据此列中的值命名文件)。
我还希望文件按“年份”排序(但这当然可以事先在 Excel 中完成。)

非常感谢您提供 bash 脚本或 Kettle/Pentaho 解决方案。 (也欢迎替代品。)

【问题讨论】:

    标签: excel bash csv split kettle


    【解决方案1】:

    我刚刚使用了您粘贴在那里的示例数据。

    awk oneliner 可以为你做到:

     awk -F, 'NR==1{title=$0;next} { print >> ($2".csv");colse}' yourCSV
    

    看下面的测试:

    kent$  l  
    total 4.0K
    -rw-r--r-- 1 kent kent 136 2011-10-05 11:04 t
    
    kent$  cat t
    Index, Name, Year, AgeGroup1, AgeGroup2, AgeGroup3
    1, Sweden, 1950, 20, 25, 27
    2, Norway, 1950, 22, 27, 28
    2, Sweden, 1951, 24, 24, 22
    
    
    kent$  awk -F, 'NR==1{title=$0;next} { print >> $2".csv"}' t
    
    kent$  head *.csv
    ==>  Norway.csv <==
    2, Norway, 1950, 22, 27, 28
    
    ==>  Sweden.csv <==
    1, Sweden, 1950, 20, 25, 27
    2, Sweden, 1951, 24, 24, 22
    

    更新

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

    【讨论】:

    • 两个 cmets: 1. 在 awk 中,在大多数情况下,您不需要双 >> 来追加。在这种情况下,你没有。 2. 使用不带括号的重定向是不可移植的(一些 awk 实现会混淆)。
    • @Dimitre Radoulov:感谢您的脚本。但是它给出了这个错误:“awk:在源代码行 1 的非法语句”。
    • @dani,您使用的是哪个操作系统和 awk 版本?你能发布你正在运行的确切命令吗?
    • @Dimitre Radoulov:亲爱的 Dimitre,我把它放在一个 .sh 文件中:awk -F, 'NR==1{title=$0;next} { print > $2".csv"}' clean_1950_2100_TEST.csv。我正在运行 Mac OS 10.6,awk 版本为 20070501。谢谢。
    • @dani,这不是我的代码 :) 无论如何,要修复错误,您需要将 print &gt; $2".csv" 更改为 print &gt; ($2".csv")
    【解决方案2】:

    如果 awk 可以接受,导出到 csv 并运行以下命令:

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

    如果您遇到以下情况,请报告:

    1. 希望在所有文件中保留标题行。
    2. 由于打开的文件过多而出现错误。

    在 Excel 之外对文件进行排序:

    sort -t, -k3,3n infile.csv | awk ...
    

    编辑:这将解决大部分问题(同时打开的文件除外):

    {
      read
      printf '%s\n' "$REPLY"
      sort -bt, -k3,3
      } < infile | 
        awk -F', *' 'NR == 1 {
          h = $0; next
          }
        {
          f = $2 ".csv"
          if (!_[f]++) 
            print h > f 
          print > f 
          }' OFS=', ' 
    

    如果您达到了 awk 实现的“打开文件过多”限制, 你可以使用这样的东西:

    awk -F, 'NR > 1 { 
      if (f) close (f)
      f = $2 ".csv"
      print > f
      }' OFS=, infile 
    

    【讨论】:

    • 如果我们关闭(f),那么我们确实需要“>>”,否则您只会在每个文件中得到一行。 (最后一行)
    • 嗨@Kent,是的,在这种情况下我们需要双倍>>。
    猜你喜欢
    • 2013-03-04
    • 2019-11-17
    • 2018-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多