如何按第一列是 n 的倍数来拆分 CSV 文件

如何按第一列是 n 的倍数来拆分 CSV 文件

我有一个很大的 csv 文件,如下所示:

1 , aaa, bbb, ...

1 , ccc, ddd, ...

2 , aaa, bbb, ...

..

10 , aaa, bbb, ...

..

1000 , aaa, bbb, ...

我想根据第一列最多为 n 的倍数,将其拆分为单独的 csv 文件,例如。对于 n=10:

0.csv 将包含:

1 , aaa, bbb, ...

1 , ccc, ddd, ...

2 , aaa, bbb, ...

..

10 , aaa, bbb, ...

1.csv 将包含:

11 , ccc, ddd, ...

12 , aaa, bbb, ...

12 , aaa, bbb, ...

..

20 , aaa, bbb, ...

问题是,我事先不知道应该为每个文件分配多少行,并且它并不是像使用 awk 那样简单地将第一列与整数匹配。

我知道这最接近我想要的:

awk -F ',' '!seen[$1]++{f=$1".csv"; print h > f};{f=$1".csv"; print >> f; close(f)}' file.csv

然而,这只按第一列值分割,这会创建太多文件,而我想将它们分组为 n 上的多个文件。

答案1

您需要使用 awk 的模数或%运算符。

例如

$ awk -F, 'BEGIN { group=0; f="0.csv"};
           $1 % 10 == 0 && !seen[$1]++ {group++; f=group".csv"};
           { print >> f}' input.txt

只要$1能被 10 整除,它就会递增变量group并更新输出文件名以匹配。

使用以下输入文件:

$ cat input.txt 
1 , aaa, bbb, ...
1 , ccc, ddd, ...
2 , aaa, bbb, ...
10 , aaa, bbb, ...
11 , aaa, bbb, ...
12 , aaa, bbb, ...
20 , aaa, bbb, ...
21 , aaa, bbb, ...
22 , aaa, bbb, ...
30 , aaa, bbb, ...
31 , aaa, bbb, ...
32 , aaa, bbb, ...
40 , aaa, bbb, ...
41 , aaa, bbb, ...
42 , aaa, bbb, ...
50 , aaa, bbb, ...
51 , aaa, bbb, ...
52 , aaa, bbb, ...
60 , aaa, bbb, ...
61 , aaa, bbb, ...
62 , aaa, bbb, ...
70 , aaa, bbb, ...
71 , aaa, bbb, ...
72 , aaa, bbb, ...
1000 , aaa, bbb, ...

它产生以下输出文件:

$ head *.csv
==> 0.csv <==
1 , aaa, bbb, ...
1 , ccc, ddd, ...
2 , aaa, bbb, ...

==> 1.csv <==
10 , aaa, bbb, ...
11 , aaa, bbb, ...
12 , aaa, bbb, ...

==> 2.csv <==
20 , aaa, bbb, ...
21 , aaa, bbb, ...
22 , aaa, bbb, ...

==> 3.csv <==
30 , aaa, bbb, ...
31 , aaa, bbb, ...
32 , aaa, bbb, ...

==> 4.csv <==
40 , aaa, bbb, ...
41 , aaa, bbb, ...
42 , aaa, bbb, ...

==> 5.csv <==
50 , aaa, bbb, ...
51 , aaa, bbb, ...
52 , aaa, bbb, ...

==> 6.csv <==
60 , aaa, bbb, ...
61 , aaa, bbb, ...
62 , aaa, bbb, ...

==> 7.csv <==
70 , aaa, bbb, ...
71 , aaa, bbb, ...
72 , aaa, bbb, ...

==> 8.csv <==
1000 , aaa, bbb, ...

简单递增的另一种方法group是使其等于$1 / 10。例如

$ awk -F, '{ group = int($1 / 10); f=group".csv" ; print >> f }' input.txt

如果您希望能够n在命令行上指定而不是对其进行硬编码:

$ awk -F, 'BEGIN { group=0; f="0.csv"};
           $1 % n == 0 && !seen[$1]++ {group++; f=group".csv"};
           { print >> f}' n=5 input.txt

相关内容