簡體   English   中英

在bash腳本中不均勻地將CSV文件拆分為多個文件

[英]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 腳本,例如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  

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM