首页 > 解决方案 > 在 bash 脚本中将 CSV 文件不均匀地拆分为多个文件

问题描述

我有一个包含几个大 csv 文件的文件夹,我希望拥有可变数量的几乎相同大小的 CSV 文件。

目前,这是我的平均规模的部门实施:

#!/bin/bash

#copy header to all resulting files parts
head -n 1 $1_2021.csv | awk -v NPROC=$(nproc) '{ for (i = 0; i < NPROC; ++i) print $0 > "file_"i".csv" }'

#copy the data but the header for each file part
tail --silent -n+2 $1* | awk -v NPROC=$(nproc) '{ part = NR % NPROC; print $0 >> "file_"part".csv" }'

where$1是文件的版本,作为参数传递给 bash 脚本,例如v1v2. 输出文件名不相关,目前file_"i".csv&file_"part".csv产生相同的文件名,其中part&i位于此范围内:(0, NPROC)

文件的一些示例v1_2020.csv(分号分隔)

DATE;COLOUR;CLOSING;CHANGE;Y  
2020-01-02;r;n;4;119  
2020-01-02;y;n;56;130  
2020-01-03;y;n;3;153  
2020-01-03;r;n;46;192  
2020-01-03;b;n;20;241  
2020-01-04;w;n;1252;252  
2020-01-05;w;n;453;253  
2020-01-06;b;y;1;279  
2020-01-06;b;n;945;294  

逐表看起来像这样:

日期 颜色 关闭 改变
2020-01-02 r n 4
2020-01-02 是的 n 56
2020-01-03 是的 n 3
2020-01-03 r n 46
2020-01-03 b n 20
2020-01-03 w n 1252
2020-01-05 w n 453
2020-01-06 b 是的 1
2020-01-06 b n 945

我想改进这种划分,使其不会在相同的日期分成不同的文件。所以它应该考虑到DATECSV 文件中的列。

电流输出NPROC=2

file_1.csv

DATE;COLOUR;CLOSING;CHANGE;Y  
2020-01-02;r;n;4;119  
2020-01-03;y;n;3;153  
2020-01-03;b;n;20;241  
2020-01-05;w;n;453;253  
2020-01-06;b;n;945;294

file_2.csv

DATE;COLOUR;CLOSING;CHANGE;Y  
2020-01-02;y;n;56;130  
2020-01-03;r;n;46;192  
2020-01-04;w;n;1252;252  
2020-01-06;b;y;1;279 

新输出NPROC=2

无论哪种类型的不均匀拆分为NPROC多个文件,都不会将日期混淆到不同的文件中。一个日期应该只放在一个文件中,但一个文件应该包含多个日期。

例如,NPROC如果符合上述条件,任何其他类型的文件拆分都可以:

file_1.csv

DATE;COLOUR;CLOSING;CHANGE;Y  
2020-01-02;r;n;4;119  
2020-01-02;y;n;56;130  
2020-01-03;y;n;3;153  
2020-01-03;r;n;46;192  
2020-01-03;b;n;20;241  

file_2.csv

DATE;COLOUR;CLOSING;CHANGE;Y  
2020-01-04;w;n;1252;252  
2020-01-05;w;n;453;253  
2020-01-06;b;y;1;279  
2020-01-06;b;n;945;294

你能给我任何关于不使用 Python 而只是使用 bash 脚本的可能解决方案的提示吗?

标签: bashcsvawk

解决方案


如果您只想拆分 csv 并为每个拆分添加标题,您可以执行以下操作:

awk -v cnt=6 -F ';' 'FNR==1{header=$0; fn=1}
!(FNR%cnt){
    fn++
    print header >"file_" fn ".csv"
}
{print $0>"file_" fn ".csv"}' file

如果要根据日期列进行上下文拆分(假设已经排序):

awk -v sp=6 -v fn=1 -F ';' 'FNR==1{header=$0}
cnt++>sp && l1!=$1 {
    fn++
    cnt=0
    print header >"file_" fn ".csv"
}
{print $0>"file_" fn ".csv"; l1=$1}' file

这里的第二个结果:

cat *.csv
DATE;COLOUR;CLOSING;CHANGE
2020-01-02;r;n;4
2020-01-02;y;n;56
2020-01-03;y;n;3
2020-01-03;r;n;46
2020-01-03;b;n;20
2020-01-03;w;n;1252
DATE;COLOUR;CLOSING;CHANGE
2020-01-05;w;n;453
2020-01-06;b;y;1
2020-01-06;b;n;945

推荐阅读