[英]Split unevenly a CSV file in multiple files in bash scripting
我有一個文件夾,里面有幾個大的 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 腳本,例如v1
或v2
。 輸出文件名不相關,當前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
Table-wise 看起來像這樣:
日期 | 顏色 | 關閉 | 改變 |
---|---|---|---|
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 | 乙 | n | 20 |
2020-01-03 | 瓦 | n | 1252 |
2020-01-05 | 瓦 | n | 453 |
2020-01-06 | 乙 | 是 | 1 |
2020-01-06 | 乙 | n | 945 |
我想改進這種划分,使其不會將相同日期分成不同的文件。 所以它應該考慮到 CSV 文件中的DATE
列。
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 腳本的可能解決方案的提示嗎?
如果您只想拆分 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
首先,使用命令行工具處理 CSV/TSV 文件可能很棘手。 awk
命令是這里的首選,但它沒有對引用的內置支持; 如果您有像第column 1; "column 2 has a ';' in it";column 3
列這樣的行column 1; "column 2 has a ';' in it";column 3
column 1; "column 2 has a ';' in it";column 3
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
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.