在awk中累积不同的行到不同的文件

时间:2018-03-16 17:11:48

标签: linux file awk

我有一个巨大的.txt文件(15 GB),拥有近3000万行。

我想根据4th column.将其行放到不同的文件中unique列的4th列在2 million.附近

file1.txt
1  10  ABC KK-LK
1  33  23  KK-LK
2  34  32  CK-LK,LK
11 332 2   JK@
11 23  2   JK2

现在,我可以将这些行分隔到相同文件夹中的不同文件,如下所示:

awk '{ print $0 >> $4"_sep.txt" }' file1.txt

它会导致4个不同的文件:

KK-LK_sep.txt
1 10 ABC KK-LK
1 33 23  KK-LK

CK-LK,LK_sep.txt
2 34 32  CK-LK,LK

JK@_sep.txt
11 332 2 JK@

最后,

JK2_sep.txt
11 23  2 JK2

我想要的是,不要将200万个文件放在一个文件夹中,将它们分成20个不同的文件夹。我可以将文件夹设为folder1,2,3 ....:

mkdir folder{1..20}

通过以下答案,我认为像下面的代码可能有用:

#!/bin/env bash

shopt -s nullglob
numfiles=(*)
numfiles=${#numfiles[@]}
numdirs=(*/)
numdirs=${#numdirs[@]}
(( numfiles -= numdirs ))
echo $numfiles
var1=$numfiles

awk -v V1=var1 '{ 
  if(V1 <= 100000) 
  { 
    awk '{ print $0 >> $4"_sep.txt" }' file1.txt

  } 

  else if(V1 => 100000) 
  { 
   cd ../folder(cnt+1)
   awk '{ print $0 >> $4"_sep.txt" }' file1.txt

  } 


}'

但是,如果有folder1文件,我怎么能把它作为循环并停止累加到100.000,然后开始向folder2添加文件等等?

2 个答案:

答案 0 :(得分:3)

也许这就是你想要的(未经测试,因为你的问题不包括我们可以测试的例子):

awk '
    !($4 in key2out) {
        if ( (++numKeys % 100000) == 1 ) {
            dir = "dir" ++numDirs
            system("mkdir -p " dir)
        }
        key2out[$4] = dir "/" $4 "_sep.txt"
    }
    { print > key2out[$4] }
' file1.txt

这依赖于GNU awk来管理内部打开文件的数量。对于其他awks,您需要将最后一行更改为{ print >> key2out[$4]; close(key2out[$4]) }或以其他方式处理有多少同时打开的文件,以避免出现“过多的打开文件”错误,例如:如果您的$ 4值通常组合在一起然后比在每次写入时打开和关闭输出文件更有效,那么您可以在$ 4值更改时执行此操作:

awk '
    $4 != prevKey { close(key2out[prevKey]) }
    !($4 in key2out) {
        if ( (++numKeys % 100000) == 1 ) {
            dir = "dir" ++numDirs
            system("mkdir -p " dir)
        }
        key2out[$4] = dir "/" $4 "_sep.txt"
    }
    { print >> key2out[$4]; prevKey=$4 }
' file1.txt

答案 1 :(得分:0)

这样的事情? 计算阈值后的唯一密钥和增量桶。

count += !keys[$4]++; 
bucket=count/100000; 
ibucket=int(bucket); 
ibucket=ibucket==bucket?ibucket:ibucket+1;    
folder="folder"ibucket