根据条件和大约行数将文件拆分为多个文件

Split file into several files based on condition and also number of lines approximately

我有一个大文件,其中包含如下示例

A222, 00000, 555
A222, 00100, 555
A222, 00200, 555
A222, 00300, 555
A222, 00000, 555
A222, 00100, 555
A222, 00000, 555
A222, 00200, 555

这是一个示例文件,其中包含顺序 header(00000) 和相关的订单详细信息(00100、00200 等)我想将文件拆分为大约 40000 行,以便每个文件都有顺序 headers 和订单详细信息一起。

我使用GNU parallel实现了40000行的拆分,但是我无法实现拆分以满足确保订单Header及其相关订单详细信息的条件全部排成一行,确保每个文件每个文件大约有 40000 行

对于上面的示例文件,如果我必须每行分割大约 5 行,我会使用下面的

parallel --pipe -N5 'cat > sample_{#}.txt' <sample.txt

但这会给我

sample1.txt
A222, 00000, 555
A222, 00100, 555
A222, 00200, 555
A222, 00300, 555
A222, 00000, 555

sample2.txt
A222, 00100, 555
A222, 00000, 555
A222, 00200, 555

第一个文件中有第二个订单 header,第二个文件中有相关的订单详细信息。

想要的应该是

sample1.txt
A222, 00000, 555
A222, 00100, 555
A222, 00200, 555
A222, 00300, 555

sample2.txt
A222, 00000, 555
A222, 00100, 555
A222, 00000, 555
A222, 00200, 555

您可以试试这个代码:

( export hdr=$(head -1 sample.txt); parallel  --pipe -N4 '{ echo "$hdr"; cat; } > sample_{#}.txt' < <(tail -n +2 sample.txt) )

我们基本上保持 header 行分开,运行 在剩余行上拆分,同时在每个拆分文件中包含 header。

单条记录:

cat file | parallel --pipe --recstart 'A222, 00000, 555' -n1 'echo Single record;cat'

多条记录(最多--block-size

cat file | parallel --pipe --recstart 'A222, 00000, 555' --block-size 100 'echo Multiple records;cat'

如果 'A222' 不保持不变:

cat file | parallel -k --pipe --regexp --recstart '[A-Z]\d+, 00000' -N1 'echo Single record;cat'

当每个订单Header有很多条记录时,可以考虑简单的

csplit -z sample.txt '/00000,/' '{*}'

这将为每个订单创建一个文件 Header。它没有考虑 ~40K 的要求,可能会产生非常多的文件,并且只有在数量有限(可能是 40 个?)不同的 Order Headers.

时才是可行的解决方案

如果您确实希望将不同的 headers 合并到一个文件中,请考虑

awk -v max=40000 '
   function flush() {
      if (last+nr>max || sample==0) {
         outfile="sample_" sample++ ".txt";
         last=0;
      }
      for (i=0;i<nr;i++) print a[i] >> outfile;
      last+=nr;
      nr=0;
   }
   BEGIN { sample=0 }
   /00000,/ { flush(); }
   {a[nr++]=[=11=]}
   END { flush() }
   ' sample.txt