Linux 在awk中将不同的行累积到不同的文件中
我有一个巨大的Linux 在awk中将不同的行累积到不同的文件中,linux,file,awk,Linux,File,Awk,我有一个巨大的.txt文件(15GB),有将近3000万行 我想根据4列将其行放入不同的文件。并且unique第4列的number约为200万。 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
.txt
文件(15GB),有将近3000万行
我想根据4列将其行放入不同的文件。
并且unique
第4列的number约为200万。
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
及
及
最后
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
}
}'
#/bin/env bash
shopt-s nullglob
numfiles=(*)
numfiles=${#numfiles[@]}
numdirs=(*/)
numdirs=${#numdirs[@]}
((numfiles-=numdirs))
echo$numfiles
var1=$numfiles
awk-V1=var1'{
如果(V1 100000)
{
cd../文件夹(cnt+1)
awk“{print$0>>$4”_sep.txt”}”file1.txt
}
}'
但是,一旦100.000
文件在folder1
中,我如何使其成为一个循环,并停止向folder2
中添加文件,等等?类似的内容?
计算唯一密钥并在阈值后增加存储桶
count += !keys[$4]++;
bucket=count/100000;
ibucket=int(bucket);
ibucket=ibucket==bucket?ibucket:ibucket+1;
folder="folder"ibucket
也许这正是您想要的(未经测试,因为您的问题不包括我们可以测试的示例):
这依赖于GNU awk来管理内部打开的文件数量。对于其他AWK,您需要将最后一行更改为{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
如果您不需要第一个文件夹中的第一个100k,第二个文件夹中的第二个100k,等等,您可以输出到(NR%20)“/“$4”\u sep.txt”
我只需要共享第四列的行在同一个文件中,但是,当第一个文件夹已满时,此代码如何将文件定向到第二个文件夹?因此,我们计算唯一键,bucket具有文件夹数。但是,我将awk'{print$0>>4“_sep.txt”}file1.txt
,它将产生一个错误:bash:!键[:event not found
您需要将这些添加到脚本中。这是一个sniplet而不是完整的脚本。我正在尝试将文件重定向到不同的文件夹,但它会重新创建“$4”\u sep.txt“
在每个文件夹中,它们有不同的行。我在我的答案中添加了另一种可能的解决方案,但在提问时,在问题中有一个可测试的示例确实很重要。我写的完全一样;)。唯一的区别是将numDirs设置为numDirs=sprintf(“%0.4d”,numDirs+1)
。这使得它总是一个4位数的目录名,这使得浏览更容易。这是个好主意,但我会在分配给dir name变量时这样做:dir=sprintf(“dir%04d”,numDirs)
。
count += !keys[$4]++;
bucket=count/100000;
ibucket=int(bucket);
ibucket=ibucket==bucket?ibucket:ibucket+1;
folder="folder"ibucket
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
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