"pause" awk 是否可以在不丢失其在文件中的位置的情况下执行其他一些命令?
Is it possible to "pause" awk to carry out some other commands without it losing its place in the file?
我有 23 个基因数据压缩文件,每个文件有 3.8 到 2400 万行。每个文件都有超过 12,000 列。我需要提取特定列中变量高于特定值的行。
通过将文件(我们称它为 ${HUGE_DATA_FILE})从 zcat 传输到 awk 并将满足条件的行打印到一个临时文件(最后用 gzip 压缩),可以很容易地做到这一点。但是,可能有 40% 的行满足条件,临时文件变得巨大。如果我同时尝试使用多个文件,非 gzip 临时文件会迅速占用所有可用内存。
我编写了一个以块为单位处理文件的脚本:它读取 100,000 行数据,将适当的行提取到一个临时文件,然后 gzip 临时文件并将其附加到输出文件。输出是正确的,但到达那里很慢。每次它启动循环来处理一个新块(第 6 行)时,它都会从头开始读取 ${HUGE_DATA_FILE}),这似乎真的是在浪费时间。
1 BLOCK_SIZE=100000
2 START_CTR=1
3 END_CTR=$(( START_CTR + BLOCK_SIZE ))
4 while [ $START_CTR -lt $MAX_LINE ]
5 do
6 zcat ${HUGE_DATA_FILE} | tail -n +${START_CTR} | head -n ${BLOCK_SIZE} | awk -F'\t' '{ if( >= 0.4) print [=11=] }' >> ${TEMP_OUTPUT_FILE}
7 gzip ${TEMP_OUTPUT_FILE}
8 cat ${TEMP_OUTPUT_FILE}.gz >> ${OUTPUT_FILE}.gz
9 START_CTR=${END_CTR}
10 END_CTR=$(( START_CTR + BLOCK_SIZE ))
11 rm ${TEMP_OUTPUT_FILE}.gz
12 done
我的问题:
- 有没有办法“暂停”zcat | awk 每隔一段时间执行第 7-11 行中的步骤而不使 zcat 在文件开头重新开始?例如,是否可以在 awk 语句中嵌入第 7-11 行,以便每次 NR 是 100000 的倍数时它们得到 运行?
- 除了制作巨大的临时文件的问题外,zcat 对于这种大小的文件来说非常慢。但是,对于这 23 个巨大的数据文件中的每一个,都有一个行数相同的信息文件。它不是 12,000 列,而是只有少数几列,其中一列具有我用来确定从庞大数据文件中提取哪些行的变量。脚本可以非常快速地读取此信息文件并记录需要从庞大数据文件中提取的行的行号。有没有什么方法可以提取行而无需实际读取庞大的数据文件来查找行尾? (或者,至少,有没有比 zcat 更快的文件读取方式?)
- 是否有其他聪明的方法来解决速度和临时文件大小的问题?
只需执行此操作而不是循环和临时文件:
zcat "$HUGE_DATA_FILE" | awk 'whatever' | gzip -c > "${OUTPUT_FILE}.gz"
顺便边学习边看Correct Bash and shell script variable capitalization and https://mywiki.wooledge.org/Quotes and copy/paste all of your shell scripts into http://shellcheck.net
我有 23 个基因数据压缩文件,每个文件有 3.8 到 2400 万行。每个文件都有超过 12,000 列。我需要提取特定列中变量高于特定值的行。
通过将文件(我们称它为 ${HUGE_DATA_FILE})从 zcat 传输到 awk 并将满足条件的行打印到一个临时文件(最后用 gzip 压缩),可以很容易地做到这一点。但是,可能有 40% 的行满足条件,临时文件变得巨大。如果我同时尝试使用多个文件,非 gzip 临时文件会迅速占用所有可用内存。
我编写了一个以块为单位处理文件的脚本:它读取 100,000 行数据,将适当的行提取到一个临时文件,然后 gzip 临时文件并将其附加到输出文件。输出是正确的,但到达那里很慢。每次它启动循环来处理一个新块(第 6 行)时,它都会从头开始读取 ${HUGE_DATA_FILE}),这似乎真的是在浪费时间。
1 BLOCK_SIZE=100000
2 START_CTR=1
3 END_CTR=$(( START_CTR + BLOCK_SIZE ))
4 while [ $START_CTR -lt $MAX_LINE ]
5 do
6 zcat ${HUGE_DATA_FILE} | tail -n +${START_CTR} | head -n ${BLOCK_SIZE} | awk -F'\t' '{ if( >= 0.4) print [=11=] }' >> ${TEMP_OUTPUT_FILE}
7 gzip ${TEMP_OUTPUT_FILE}
8 cat ${TEMP_OUTPUT_FILE}.gz >> ${OUTPUT_FILE}.gz
9 START_CTR=${END_CTR}
10 END_CTR=$(( START_CTR + BLOCK_SIZE ))
11 rm ${TEMP_OUTPUT_FILE}.gz
12 done
我的问题:
- 有没有办法“暂停”zcat | awk 每隔一段时间执行第 7-11 行中的步骤而不使 zcat 在文件开头重新开始?例如,是否可以在 awk 语句中嵌入第 7-11 行,以便每次 NR 是 100000 的倍数时它们得到 运行?
- 除了制作巨大的临时文件的问题外,zcat 对于这种大小的文件来说非常慢。但是,对于这 23 个巨大的数据文件中的每一个,都有一个行数相同的信息文件。它不是 12,000 列,而是只有少数几列,其中一列具有我用来确定从庞大数据文件中提取哪些行的变量。脚本可以非常快速地读取此信息文件并记录需要从庞大数据文件中提取的行的行号。有没有什么方法可以提取行而无需实际读取庞大的数据文件来查找行尾? (或者,至少,有没有比 zcat 更快的文件读取方式?)
- 是否有其他聪明的方法来解决速度和临时文件大小的问题?
只需执行此操作而不是循环和临时文件:
zcat "$HUGE_DATA_FILE" | awk 'whatever' | gzip -c > "${OUTPUT_FILE}.gz"
顺便边学习边看Correct Bash and shell script variable capitalization and https://mywiki.wooledge.org/Quotes and copy/paste all of your shell scripts into http://shellcheck.net