Bash 高效连接>;100个文件
我有一个列表,其中包含>100个以制表符分隔的文件,包含500-800万行和16列(总是以相同的顺序排列)。从每个文件中,我需要提取5个特定列,包括一个标识符列。我的最终输出(以3个输入文件为例)应该是4个文件,包含以下列:Bash 高效连接>;100个文件,bash,performance,join,merge,Bash,Performance,Join,Merge,我有一个列表,其中包含>100个以制表符分隔的文件,包含500-800万行和16列(总是以相同的顺序排列)。从每个文件中,我需要提取5个特定列,包括一个标识符列。我的最终输出(以3个输入文件为例)应该是4个文件,包含以下列: 输出1:ID,VAR1 输出2:VAR2.1、VAR2.2、VAR2.3 输出3:VAR3.1、VAR3.2、VAR3.3 输出4:VAR4.1、VAR4.2、VAR4.3 其中“.1”、“.2”和“.3”分别表示该列源于第一个、第二个和第三个输入文件 我的问题是,输入
- 输出1:ID,VAR1
- 输出2:VAR2.1、VAR2.2、VAR2.3
- 输出3:VAR3.1、VAR3.2、VAR3.3
- 输出4:VAR4.1、VAR4.2、VAR4.3
ID=1
VAR1=6
VAR2=9
VAR3=12
VAR4=16
while read FILE;do
sort -k${ID},${ID} < ${FILE} | awk -v ID=${ID} -v VAR1=${VAR1} -v VAR2=${VAR2} -v VAR3=${VAR3} -v VAR4=${VAR4} 'BEGIN{OFS="\t"};{print $ID,$VAR1 > "tmp1";print ${ID},$VAR2 > "tmp2";print ${ID},$VAR3 > "tmp3";print ${ID},$VAR4 > "tmp4"}'
awk 'FNR==NR{a[$1]=$1;next};{if(($1 in a)==0){print $0 > "tmp5"}}' output1 tmp1
cat output1 tmp5 > foo && mv foo output1
join -e "NA" -a1 -a2 -t $'\t' -1 1 -2 1 output2 -o auto tmp2 > bar2 && mv bar2 output2
join -e "NA" -a1 -a2 -t $'\t' -1 1 -2 1 output3 -o auto tmp3 > bar3 && mv bar2 output3
join -e "NA" -a1 -a2 -t $'\t' -1 1 -2 1 output4 -o auto tmp4 > bar4 && mv bar2 output4
rm tmp?
done < files.list
sort -k1,1 output1 > foo && mv foo output1
ID=1
VAR1=6
VAR2=9
VAR3=12
VAR4=16
读取文件时;做
sort-k${ID},${ID}<${FILE}| awk-v ID=${ID}-v VAR1=${VAR1}-v VAR2=${VAR2}-v VAR3=${VAR3}-v VAR4=${VAR4}开始{OFS=“\t};{print$ID,$VAR1>“tmp1”;print${ID},$VAR2>“tmp2”;print${ID},$VAR3>“tmp3”;print${ID},$VAR4>“tmp4”}”
awk'FNR==NR{a[$1]=$1;next};{if((a中的$1)==0){print$0>“tmp5”}}输出1 tmp1
cat输出1 tmp5>foo和mv foo输出1
连接-e“NA”-a1-a2-t$'\t'-11-21输出2-o自动tmp2>bar2和mv bar2输出2
连接-e“NA”-a1-a2-t$'\t'-11-2 1输出3-o自动tmp3>bar3和mv bar2输出3
连接-e“NA”-a1-a2-t$'\t'-11-21输出4-o自动tmp4>bar4和mv bar2输出4
rm tmp?
完成foo&mv foo输出1
最后一句话:我对output1使用
cat
,因为VAR1中相同ID的所有值在所有输入文件中都是相同的(我在预处理文件时已经确保了这一点)。因此,我可以将尚未包含的行附加到output1的底部,并对最终的输出文件进行排序。首先,您必须找出大部分时间都浪费在哪里。你可以“呼应”运行X;时间./X`并确保您没有尝试优化脚本中最快的部分
您只需在后台并行运行三个连接(cmd args)&
,然后等待它们全部完成。如果这需要1秒,而之前的awk
部分需要10分钟,那么这不会有多大帮助
您还可以将wait
置于cat output 1 tmp5…
之前和最后一行sort-k1…
之前。要使其起作用,您必须以不同的方式命名临时文件,并在join
s之前重命名它们。其思想是为后台的第一个文件生成三个并行联接的输入,等待
,然后重命名这些文件,在后台运行联接
并生成下一个输入。循环完成后,只需等待最后一次加入即可。如果awk
部件消耗的CPU时间与join
s相当,这将有所帮助
嗯,,您可以创建更复杂的并行执行场景。为什么排序?好问题NEGR KITAEC
并检查bar2和&mv bar2输出2
,下一行bar3和&mv bar2…
。在cat-uput1 tmp5>foo中uputt是原始脚本中的错误还是仅在这里?第一行awk
命令使用ID
,VAR1
,VAR2
,VAR3
,VAR4
作为输入变量。何时填写?您从哪里获得ID
?这是第一列,而VAR1
是第二列吗?谢谢你的提示!实际上,while循环中第一行的sort
-命令占用了大部分时间。我原以为这比在连接之前对单独的文件进行排序要快,但忘了我可以并行地进行排序。现在,我并行运行3个join
s,在每个并行运行中,首先提取所需的列,然后进行排序
。这使我的脚本的运行时间减少了一半