在 UNIX 中根据第一列的最后一位数字分割文件

在 UNIX 中根据第一列的最后一位数字分割文件

我有一个文件sales_$date.csv。我想根据第一列(ITEM)的最后一位数字将其拆分为 10 个文件。所以实际上文件会被分成 10 个文件,如sales_$date-01.csvsales_$date-02.csv、.. 等等。我还需要保留所有文件中的标题。列长度​​ (ITEM) 值不固定。此过程需要每天每 :45 分钟运行一次。下面是例子

sales_$date.csv文件:FILE=sales_$日期商品、数量、商店、BUYABLEFLAG 4000,1,13805,Y 4001,3,1456,N 5010,2,14534,Y 7200,5,14566,N 4002,2,6534534,N 5611 ,9,34234,Y 7832,32,6575,N

sales_$date-01.csv应该有以 0 结尾的项目记录(参见第一列 ITEM 值):

ITEM,QTY,STORE,BUYABLEFLAG
4000,1,13805,Y
5010,2,14534,Y
7200,5,14566,N

sales_$date-02.csv应该有以 1 结尾的项目记录(参见第一列 ITEM 值):

ITEM,QTY,STORE,BUYABLEFLAG
4001,3,1456,N
5611,9,34234,Y

sales_$date-03.csv应该有以 2 结尾的项目记录(参见第一列 ITEM 值):

ITEM,QTY,STORE,BUYABLEFLAG
4002,2,6534534,N
7832,32,6575,N

此外,所有文件名(即 sales_date-01、sales_date-02、sales_date-03)都位于名为 FILE_NAME 的变量中。

答案1

如果你的文件只是很大,而不是非常庞大,你可以使用以下命令对文件进行 10 次遍历:

for digit in 0 1 2 3 4 5 6 7 8 9 ; do
    egrep "^ITEM,|^...$digit" sales.csv >sales-0$digit.csv
done

答案2

在单次传递中:

awk '
    NR == 1 { for (i=1; i<=10; i++) print > sprintf("sales-%02d.csv", i) }
    NR > 1  { print > sprintf("sales-%02d.csv", $1%10+1) }
' data

答案3

我会为此分解perl- 它有点冗长,但希望更清楚它在做什么?它单遍工作,解析行中的“id”,并基于该文件打开一个文件。它实际上会不是创建文件,否则它会是空的 - 我称其为一项功能,但如果您不喜欢它,很容易更改。

#!/usr/bin/perl
use strict;
use warnings;

#read header row from STDIN or file specified on command line (like grep/sed/awk)
my $header = <>; 

#set up file handles to write to 
my %file_for; 

#iterate STDIN or files on command line
while ( <> ) { 
    #get 'first digit before a comma' on current line. 
    my ( $file_id ) = /(\d),/;

    #open the file, if we haven't already. (it auto closes at script exit)
    if ( not defined $file_for{$file_id} ) {
        open ( $file_for{$file_id}, '>', "sales-0".$file_id.".csv" ) or warn $!;
        #print the header row
        print {$file_for{$file_id}} $header;
    }
    #select this file for output, and print the current line. 
    select $file_for{$file_id} and print;
}

相关内容