在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" }'

其中$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  

按表显示如下:

关闭>nn<20>n<1252>n<1>
日期颜色更改
2020-01-02rn4
2020-01-02yn56
2020-01-03y3
2020-01-03r46
2020-01-03bn
2020-01-03w
2020-01-05w453
2020-01-06by
2020-01-06bn945

如果您只想拆分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
awk -F';' -v NPROC=2 '
NR == 1 {head = $0; next}
!($1 in dates) {
n = (n + 1) % NPROC
file = "out_" n ".csv"
if (!(file in created)) {
print head > file
created[file]
}
dates[$1] = file
}
{ print > dates[$1] }
' v1_2020.csv

由于NPROC=2,将创建两个输出文件:

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

首先,使用命令行工具处理CSV/TSV文件可能很棘手。awk命令是这里的目标,但它没有内置的对引用的支持;如果您有一个类似column 1; "column 2 has a ';' in it";column 3的行,那么awk -F';'将把它看作$1="column 1"$2=""column to has a '"$3="'in it""$4="column3"

如果您的数据中没有类似的内容,那么它非常简单。首先,您想将每个日期写入自己的文件:

awk -F';'  '{print >>$1".csv"}'

这将使您获得以日期命名的文件,如2020-01-02.csv

现在,您可以将这些数据合并到NPROC文件中,只要您只合并整个文件,就不会将给定日期的数据拆分到多个文件中。这里有一种简单(不一定优雅!(的方法:

declare -i lines=$(cat *-*-*.csv | wc -l) chunk cur
(( chunk = lines / NPROC, cur = 1 ))
for f in *-*-*.csv; do
cat "$f" >>"file_$cur.csv"
if (( $(wc -l <"file_$cur.csv") >= chunk )); then
(( cur += 1 ))
fi
done

相关内容

  • 没有找到相关文章

最新更新