2015-08-20 9 views
1

我有大的.csv文件(40MB〜),我想通过几个条件,从而分解成更小的文件,并相应地命名他们的数据:由第3列的内容如何突破大名为“.csv”文件到基于多种条件下微小的文件?

  1. 独立的文件,
  2. 独立从由内容第四科拉姆点1输出,

下面是棘手的部分:

由2个先前操作
  • 创建输出检查是否有在第11列中的任何数据,如果是的话那么这个数据分开相应的内容,之后单独由17列的内容 - >然后保存输出 /或/与/
  • 如果在11列检查列第15无数据并相应地分开。接下来检查17列,并通过第17列将这些数据分开 - >保存输出。
  • 我有这样的事情在VBA,但它太路为大文件缓慢和Excel有时会轰然倒下。对于像这样的多个文件,需要很长时间才能手动删除它们,然后将vba放入工作中。

    这是可能通过这么多条件削减文件?

    在此先感谢您的帮助。

    的exaple: (头是列#)

    1  2 3 4 11 15 17 
    Date  Time COUNTRY CITY CHECK TEST TEST2 
    2015-08-20 11:54 ENGLAND ABINGDON  1  1 
    2015-08-21 12:54 ENGLAND BATLEY   2  5 
    2015-08-22 13:54 ENGLAND FROME   2  6 
    2015-08-23 14:54 ENGLAND FROME 2  1 
    2015-08-24 15:54 USA CALIFORNIA   4  8 
    2015-08-25 16:54 USA CONNECTICUT   4  9 
    2015-08-26 17:54 USA DELAWARE 1    8 
    2015-08-27 18:54 GERMANY SAXONY   6  9 
    2015-08-28 19:54 GERMANY SAXONY   6  10 
    2015-08-27 18:54 GERMANY SAXONY   4  11 
    2015-08-28 19:54 GERMANY SAXONY   4  14 
    2015-08-29 20:54 GERMANY HESSE     8 
    2015-08-29 20:54 GERMANY HESSE 1    8 
    
    File1      
    2015-08-20 11:54 ENGLAND ABINGDON  1  1 
    
    File2      
    2015-08-21 12:54 ENGLAND BATLEY   2  5 
    
    File3      
    2015-08-22 13:54 ENGLAND FROME   2  6 
    
    File4      
    2015-08-23 14:54 ENGLAND FROME 2    1 
    
    File5      
    2015-08-24 15:54 USA CALIFORNIA   4  8 
    
    File6      
    2015-08-25 16:54 USA CONNECTICUT   4  9 
    
    File7      
    2015-08-26 17:54 USA DELAWARE 1    8 
    
    File8      
    2015-08-27 18:54 GERMANY SAXONY   4  9 
    2015-08-28 19:54 GERMANY SAXONY   4  10 
    
    File9      
    2015-08-27 18:54 GERMANY SAXONY   6  11 
    2015-08-28 19:54 GERMANY SAXONY   6  14 
    
    File10      
    2015-08-29 20:54 GERMANY HESSE     8 
    
    File11      
    2015-08-29 20:54 GERMANY HESSE 1    8 
    
    +1

    也许向我们展示10-20行混合数据以及处理后的外观。 –

    +0

    @MarkSetchell我在问题描述中添加了“示例”。 – Thatsnotmyname

    +0

    你有没有在bash中尝试过任何东西?你的分隔符是什么?标签? – carlspring

    回答

    0

    你的数据是所有的地方!它不在您描述的列中,也不是制表符分隔的。你不会让生活变得轻松!

    试试这个awk与你的真实数据,看它是否产生,你可以使用一个输出文件名。

    awk -F'\t' '{ 
        f=$3 "_" $4    # filename = field3 _ field4 
        if(length($11)){   # if f11 not null 
         f=f "_A_" $11 "_" $17 # filename = filename _A_ field11 _ field17 
        }else{      # else 
         f=f "_B_" $15 "_" $17 # filename = filename _B_ field15 _ field17 
        } 
        print f}' file.csv 
    

    你应该得到这样的事情

    ENGLAND_ABINGDON_A_3_1 
    ENGLAND_ABINGDON_A_4_2 
    GENRMANY_SAXONY_B_5_3 
    

    基本上它采用awk并告诉它你的字段分隔标签。然后,它会检查每个订单,并通过看你如何描述字段建立在可变f一个输出文件名。

    如果分开你的数据,你怎么个意思,你其实可以通过简单地改变最后一行是这样做的当前行与相应名称的文件的输出:

    awk -F'\t' '{ 
        f=$3 "_" $4    # filename = field3 _ field4 
        if(length($11)){   # if f11 not null 
         f=f "_A_" $11 "_" $17 # filename = filename _A_ field11 _ field17 
        }else{      # else 
         f=f "_B_" $15 "_" $17 # filename = filename _B_ field15 _ field17 
        } 
        print > f}' file.csv 
    

    基本上它打印的文件,而不是打印它的名字,如果你改变

    print f 
    

    print > f 
    

    工作了头

    如果您想对每个输出呸一个头,我们需要工作有点困难......

    首先,我们需要从原始文件中保存的头,因此,如果我们假设是记录号1,我们会做

    awk -F'\t' ' 
        NR==1 {header=$0}   # save first line as header 
        {f=$3 "_" $4    # filename = field3 _ field4 
        ... 
        ... as before 
    

    现在,我们需要输出,每当我们开始写入新文件的标题行,这是“好玩”因为我们只是CR动态为每一行提供输出文件名!所以,我们需要“记住”我们写了什么文件,然后在写入新文件时只发出一个头文件。我在这里没有一套体面的数据,所以我在猜测这一点!

    awk -F'\t' ' 
        NR==1 {header=$0}   # save first line as header 
        {f=$3 "_" $4    # filename = field3 _ field4 
        if(length($11)){   # if f11 not null 
         f=f "_A_" $11 "_" $17 # filename = filename _A_ field11 _ field17 
        }else{      # else 
         f=f "_B_" $15 "_" $17 # filename = filename _B_ field15 _ field17 
        } 
        # Emit header if first write to this filename 
        if(!(f in fileswritten)){ 
         fileswritten[f]++   # note that we have written to this file 
         print header > f   # emit header 
        } 
        print > f}' file.csv 
    
    +0

    谢谢。我会在空闲时间检查。 – Thatsnotmyname

    +0

    马克,我部署了该脚本及其工作,但告诉我,有没有办法将原始文件头添加到每个文件?我的意思是列的名字? – Thatsnotmyname

    +0

    我在最后添加了一些代码来尝试获取标题,但未经测试。它应该足够接近,但你要弄清楚它是否有任何错误。 –

    0

    这个答案是不完整的,但大致说明你需要做什么:

    #!/bin/bash 
    
    # Get list of countries: 
    countries=`cat file1.csv | cut -f 3 -d$'\t'| grep -v 3 | grep -v COUNTRY | uniq` 
    
    for country in ${countries}; do 
        # Get list of cities per country: 
        cities=`cat file1.csv | grep ${country} | cut -f 4 -d$'\t' | uniq` 
    
        # Get data per country: 
        cat file1.csv | grep ${country} > file1-${country}.csv 
    
        # Get data per city per country: 
        for city in ${cities}; do 
        echo ${country}:${city} 
    
        cat file1.csv | grep ${country} | grep ${city} > file1-${country}-${city}.csv 
        done 
    
        # Created output by 2 previous operations check if there is any data in 11th column, 
        # if yes then separate this data accordingly to content and after that separate that 
        # by content of 17th column -> then save outputs /OR/AND/
        # Column 11 is at position 5 in your data. 
        check=`cat file1.csv | grep ${country} | cut -f 5 -d$'\t' | uniq` 
        for check in ${checks}; do 
         echo ${country}:${city}:${check} 
    
         cat file1.csv | grep ${country} | grep ${city} > file1-${country}-${city}-${check}.csv 
    
         # TODO: Further split this, I assume you get the drift by now. 
        done 
    
        # If there is no data in column 11 check column 15th and separate accordingly. 
        # Next check 17 column and separate this data by 17th column -> save outputs. 
        # TODO: Further split this, I assume you get the drift by now. 
    
    done 
    
    +0

    谢谢你的回答。今天晚些时候我需要深入研究。顺便说一下,如果在编号列之间有数据,我认为它们会被复制过来? – Thatsnotmyname

    +0

    给脚本一个去,你会看到。数据被复制,是的。这很直接,如果你玩弄它。 – carlspring

    +0

    carlspring,我正在检查脚本,到目前为止它的工作需要进一步的mods,但是我会问,就像我问Mark一样,是否有任何方法为每个文件添加标题?提前致谢。 – Thatsnotmyname

    0

    我建议写一个小脚本,并使用Java库CSVFormat:

    private static final String[] FILE_HEADER_MAPPING = {"Date", "Time" ,"COUNTRY", .... }; 
    csvFileParser = new CSVParser(fileReader, csvFileFormat); 
         List<CSVRecord> csvRecords = csvFileParser.getRecords(); 
    

    然后访问第11栏你必须做

    for (int i = 1; i < csvRecords.size(); i++) { 
        boolean publishAccount = true; 
        CSVRecord record = csvRecords.get(i); 
        /// here how to access 
        record.get("Fiel column 11"); 
    } 
    
    +0

    感谢您的回答,我还需要检查该脚本并尝试哪个操作更快。说实话,我不知道如何把你的脚本工作。 – Thatsnotmyname

    +0

    如果你创建了一个简单的java程序,你可以在你的主类中编写这个程序,并简单地通过你的unix脚本调用它。我喜欢这种方式,因为它很容易阅读和修改。你只需要在其中包含csv库。另外,在java中,你可以在字符串中使用方法'split' – Vargan