Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 将大型gz文件拆分为较小的文件,以过滤和分发内容_Bash_Awk_Sbatch - Fatal编程技术网

Bash 将大型gz文件拆分为较小的文件,以过滤和分发内容

Bash 将大型gz文件拆分为较小的文件,以过滤和分发内容,bash,awk,sbatch,Bash,Awk,Sbatch,我有一个大小为81G的gzip文件,我解压了它,解压后的文件大小是254G。我想实现一个bash脚本,它接受gzip文件并根据第一列将其拆分。第一列的值范围为1-10。我想将这些文件分成10个子文件,其中第一列中的值为1的所有行被放入1个文件中。第一列中值为2的所有行都被放入第二个文件,以此类推。当我这样做时,我不想把第3列和第5列放在新的子文件中。此外,该文件是选项卡分隔的。例如: col_1 col_2. col_3. col_4. col_5. col_6 1.

我有一个大小为81G的gzip文件,我解压了它,解压后的文件大小是254G。我想实现一个bash脚本,它接受gzip文件并根据第一列将其拆分。第一列的值范围为1-10。我想将这些文件分成10个子文件,其中第一列中的值为1的所有行被放入1个文件中。第一列中值为2的所有行都被放入第二个文件,以此类推。当我这样做时,我不想把第3列和第5列放在新的子文件中。此外,该文件是选项卡分隔的。例如:

col_1    col_2.   col_3.  col_4.  col_5.  col_6
1.       7464      sam.    NY.     0.738.  28.9
1.       81932.    Dave.   NW.     0.163.  91.9
2.       162.      Peter.  SD.     0.7293. 673.1
3.       7193.     Ooni    GH.     0.746.  6391
3.       6139.     Jess.   GHD.    0.8364. 81937
3.       7291.     Yeldish HD.     0.173.  1973
gunzip -c infile.gz |
awk '
    { $0 = $1 OFS $2 OFS $4 OFS $6 }
    NR==1 { hdr = $0; next }
    $1 != prev { close(gzip); gzip="gzip > \047"$1".csv.gz\047"; prev=$1 }
    !seen[$1]++ { print hdr | gzip }
    { print | gzip }
'
上面的文件将生成三个不同的gzip文件,以便从每个新子文件中删除col_3和col_5。我所做的是

#!/bin/bash
#SBATCH --partition normal
#SBATCH --mem-per-cpu 500G
#SBATCH --time 12:00:00
#SBATCH -c 1



awk -F, '{print > $1".csv.gz"}' file.csv.gz


但这并没有产生预期的结果。我也不知道如何从新的子文件中删除col_3和col_5。
就像我说的gzip文件是81G,因此,我正在寻找一个有效的解决方案。如果你有真知灼见,我们将不胜感激。

你必须解压和再压缩;要去掉第3列和第5列,可以使用GNU cut,如下所示:

gunzip-c infie.gz\ |切-补-f3,5\ |awk“{print | gzip>$1 csv.gz}” 或者您可以删除awk中的列:

gunzip-c infie.gz\ |awk-vofs='\t'{print$1,$2,$4,$6 | gzip>$1csv.gz}'
你必须解压和再压缩;要去掉第3列和第5列,可以使用GNU cut,如下所示:

gunzip-c infie.gz\ |切-补-f3,5\ |awk“{print | gzip>$1 csv.gz}” 或者您可以删除awk中的列:

gunzip-c infie.gz\ |awk-vofs='\t'{print$1,$2,$4,$6 | gzip>$1csv.gz}' 差不多

zcat input.csv.gz | cut-f1,2,4,6-| awk'{print | gzip-c>$1 csv.gz}' 解压缩文件,删除字段3和5,根据第一列保存到相应的压缩文件。

类似

zcat input.csv.gz | cut-f1,2,4,6-| awk'{print | gzip-c>$1 csv.gz}'
解压缩文件,删除字段3和5,并根据第一列保存到相应的压缩文件。

如果文件始终按第一个字段排序,则使用任何awk都能可靠地进行移植,如示例所示:

col_1    col_2.   col_3.  col_4.  col_5.  col_6
1.       7464      sam.    NY.     0.738.  28.9
1.       81932.    Dave.   NW.     0.163.  91.9
2.       162.      Peter.  SD.     0.7293. 673.1
3.       7193.     Ooni    GH.     0.746.  6391
3.       6139.     Jess.   GHD.    0.8364. 81937
3.       7291.     Yeldish HD.     0.173.  1973
gunzip -c infile.gz |
awk '
    { $0 = $1 OFS $2 OFS $4 OFS $6 }
    NR==1 { hdr = $0; next }
    $1 != prev { close(gzip); gzip="gzip > \047"$1".csv.gz\047"; prev=$1 }
    !seen[$1]++ { print hdr | gzip }
    { print | gzip }
'
否则:

gunzip -c infile.gz |
awk 'BEGIN{FS=OFS="\t"} {print (NR>1), NR, $0}' |
sort -k1,1n -k3,3 -k2,2n |
cut -f3- |
awk '
    { $0 = $1 OFS $2 OFS $4 OFS $6 }
    NR==1 { hdr = $0; next }
    $1 != prev { close(gzip); gzip="gzip > \047"$1".csv.gz\047"; prev=$1 }
    !seen[$1]++ { print hdr | gzip }
    { print | gzip }
'

第一个awk在前面添加一个数字,以确保在排序阶段,标题行在其余行之前排序,并添加行号,以便具有相同原始第一字段值的行保留其原始输入顺序。然后,我们按照第一个字段进行排序,然后删除第一步中添加的两个字段,然后使用awk以可靠和可移植的方式创建单独的输出文件,确保每个输出文件都从头的副本开始。我们在运行时关闭每个输出文件,这样脚本就可以使用任何awk处理任意数量的输出文件,甚至可以使用GNU awk高效地处理大量的输出文件。它还确保正确引用每个输出文件名,以避免全局搜索、分词和文件名扩展。

如果文件始终按示例中所示的第一个字段排序,则使用任何awk都能可靠地进行移植:

col_1    col_2.   col_3.  col_4.  col_5.  col_6
1.       7464      sam.    NY.     0.738.  28.9
1.       81932.    Dave.   NW.     0.163.  91.9
2.       162.      Peter.  SD.     0.7293. 673.1
3.       7193.     Ooni    GH.     0.746.  6391
3.       6139.     Jess.   GHD.    0.8364. 81937
3.       7291.     Yeldish HD.     0.173.  1973
gunzip -c infile.gz |
awk '
    { $0 = $1 OFS $2 OFS $4 OFS $6 }
    NR==1 { hdr = $0; next }
    $1 != prev { close(gzip); gzip="gzip > \047"$1".csv.gz\047"; prev=$1 }
    !seen[$1]++ { print hdr | gzip }
    { print | gzip }
'
否则:

gunzip -c infile.gz |
awk 'BEGIN{FS=OFS="\t"} {print (NR>1), NR, $0}' |
sort -k1,1n -k3,3 -k2,2n |
cut -f3- |
awk '
    { $0 = $1 OFS $2 OFS $4 OFS $6 }
    NR==1 { hdr = $0; next }
    $1 != prev { close(gzip); gzip="gzip > \047"$1".csv.gz\047"; prev=$1 }
    !seen[$1]++ { print hdr | gzip }
    { print | gzip }
'

第一个awk在前面添加一个数字,以确保在排序阶段,标题行在其余行之前排序,并添加行号,以便具有相同原始第一字段值的行保留其原始输入顺序。然后,我们按照第一个字段进行排序,然后删除第一步中添加的两个字段,然后使用awk以可靠和可移植的方式创建单独的输出文件,确保每个输出文件都从头的副本开始。我们在运行时关闭每个输出文件,这样脚本就可以使用任何awk处理任意数量的输出文件,甚至可以使用GNU awk高效地处理大量的输出文件。它还确保正确引用每个输出文件名,以避免全局搜索、分词和文件名扩展。

您的字段分隔符是什么?多个空格,一个制表符还是一个逗号?@Cyrus它说制表符是分开的。标题行是真实的还是用于说明的?它总是用制表符分开的。@BenjaminW。这是为了举例说明。你的字段分隔符是什么?多个空格,一个制表符还是一个逗号?@Cyrus它说制表符是分开的。标题行是真实的还是用于说明的?它总是用制表符分开的。@BenjaminW。这是为了举例说明。虽然我个人会对任何新的压缩文件使用zstandard over gzip。这会不会覆盖现有的输出文件,以至于每个n.csv.gz最后只包含一个输入行的数据?@John no,第一次调用gzip的管道将保持打开状态,直到awk终止或在其上调用close,因此gzip只在每个唯一$1调用一次,而不是在每个输入行调用一次。虽然我个人会对任何新的压缩文件使用zstandard over gzip。这不会覆盖现有的输出文件,这样,每个n.csv.gz最终只包含一个输入行中的数据?@John no,第一次调用的管道
gzip将一直保持打开状态,直到awk终止或对其调用close,因此gzip只在每个唯一$1调用一次,而不是在每个输入行调用一次。谢谢您的评论。我照你的建议做了。但是,当我尝试上载生成的文件时,出现以下错误:EOFError:压缩文件在到达流结束标记之前结束。@John是否可能您的磁盘空间不足,无法保存输出文件,因此导致部分文件被写入?我打开了它创建的第一个文件。如果磁盘空间不足,它不应该创建其他文件,但它确实创建了其他文件。@John第一次遇到第1列中的相应值时,它会创建每个文件。因此,我如何继续,因为我保留了500G来处理gzip文件。我原来的gzip文件是81G。这就是为什么我考虑根据第一列将其拆分成更小的文件。谢谢您的评论。我照你的建议做了。但是,当我尝试上载生成的文件时,出现以下错误:EOFError:压缩文件在到达流结束标记之前结束。@John是否可能您的磁盘空间不足,无法保存输出文件,因此导致部分文件被写入?我打开了它创建的第一个文件。如果磁盘空间不足,它不应该创建其他文件,但它确实创建了其他文件。@John第一次遇到第1列中的相应值时,它会创建每个文件。因此,我如何继续,因为我保留了500G来处理gzip文件。我原来的gzip文件是81G。这就是为什么我考虑根据第一列将其拆分为更小的文件。