GNU parallel和awk之间的冲突(拆分列并筛选某些行)

GNU parallel和awk之间的冲突(拆分列并筛选某些行),awk,gnu-parallel,Awk,Gnu Parallel,我正在处理许多大型gz文件,如下面的示例(这里只显示前5行) 下面是我想要的输出 在这里,我将第二列拆分为“z”,并根据第二列和第三列(拆分后)选择行($2==1,$3>20000)。我将其保存为txt。下面的命令工作正常 zcat InputData.txt.gz | awk -F "_" '$1=$1' | awk '{if ($2==1 && $3>20000) {print}}' > OutputData.txt ENSG00000223972.4

我正在处理许多大型gz文件,如下面的示例(这里只显示前5行)

下面是我想要的输出

在这里,我将第二列拆分为“z”,并根据第二列和第三列(拆分后)选择行($2==1,$3>20000)。我将其保存为txt。下面的命令工作正常

zcat InputData.txt.gz | awk -F "_"  '$1=$1' | awk '{if ($2==1 && $3>20000) {print}}'  > OutputData.txt

ENSG00000223972.4   1 54421 A G b37 42552   28  28  0.039548    0.680357    0.0741142   0.179725
ENSG00000223972.4   1 54490 G A b37 42621   112 120 0.176471    0.00824733  0.247533    0.093081
但是我想使用GNU并行来加速这个过程,因为我有很多大的gz文件要处理。然而,GNU parallel和awk之间似乎存在一些冲突,可能是在报价方面

我尝试按如下所示单独定义awk选项,但它在输出文件中没有给出任何信息

在下面的命令中,我只在一个输入文件上运行并行程序。但是我想在多个输入文件上运行,并保存多个输出文件,每个输出文件对应一个输入文件

比如说,

InputData_1.txt.gz到OutputData_1.txt

InputData_2.txt.gz到OutputData_2.txt

awk1='{ -F "_"  "$1=$1" }'
awk2='{if ($2==1 && $3>20000) {print}}' 
parallel "zcat {} | awk '$awk1' |awk '$awk2' > OutputData.txt" ::: InputData.txt.gz
有人对这项任务有什么建议吗? 多谢各位


根据@karakfa的建议,这是一个解决方案

chr=1
RegionStart=10000
RegionEnd=50000
zcat InputData.txt.gz | awk -v chr=$chr -v start=$RegionStart -v end=$RegionEnd '{split($2,NewDF,"_")} NewDF[1]==chr && NewDF[2]>start && NewDF[2]<end {gsub("_"," ",$2) ; print > ("OutputData.txt")}' 

#This also works using parallel

awkbody='{split($2,NewDF,"_")} NewDF[1]==chr && NewDF[2]>start && NewDF[2]<end {gsub("_"," ",$2) ; print > ("{}_OutputData.txt")}'
parallel "zcat {} | awk -v chr=$chr -v start=$RegionStart -v end=$RegionEnd '$awkbody' " ::: InputData_*.txt.gz
chr=1
RegionStart=10000
区域编号=50000
zcat InputData.txt.gz | awk-v chr=$chr-v start=$RegionStart-v end=$RegionEnd'{split($2,NewDF,“”)}NewDF[1]==chr&&NewDF[2]>start&&NewDF[2](“OutputData.txt”)}
#这也适用于使用并行
awkbody='{split($2,NewDF,“{”)}NewDF[1]==chr&&NewDF[2]>start&&NewDF[2](“{}\u OutputData.txt”)}'
并行“zcat{}awk-v chr=$chr-v start=$RegionStart-v end=$RegionEnd'$awkbody':::InputData_*.txt.gz

输入文件
InputData\u 1.txt.gz
的输出文件名将是
InputData\u 1.txt.gz\u OutputData.txt

一种方法是使用
split

$ awk '{split($2,f2,"_")} 
   f2[1]==1 && f2[2]>20000 {gsub("_"," ",$2); print > (FILENAME".output")}' file

但是,如果您通过stdin提供数据,
awk
将不会捕获要写入的文件名。您需要将其作为变量传递给脚本……

一种方法是使用
split

$ awk '{split($2,f2,"_")} 
   f2[1]==1 && f2[2]>20000 {gsub("_"," ",$2); print > (FILENAME".output")}' file

但是,如果您通过stdin提供数据,
awk
将不会捕获要写入的文件名。您需要将其作为一个变量传递给脚本,也许…

简单的解决方案是将过滤器组合成单个
awk
脚本,而不是且只有并行才能工作

下面是一个示例解决方案,它只扫描整个
input.txt
一次(性能的两倍):

说明:
BEGIN{FS=“[]*[\u]?”}
将字段分隔符设置为多个“或””\

$2==1&&$7>20000{print}
仅打印第二个字段==1和7nt字段>2000的行

调试脚本示例:

BEGIN{FS="[ ]*[_]?"}
{
    for(i = 1; i <= NF; i++) printf("$%d=%s%s",i, $i, OFS);
    print "";
}
$2==1 && $7 > 20000 {print}

简单的解决方案是将过滤器组合到单个
awk
脚本中,然后并且只有并行才能工作

下面是一个示例解决方案,它只扫描整个
input.txt
一次(性能的两倍):

说明:
BEGIN{FS=“[]*[\u]?”}
将字段分隔符设置为多个“或””\

$2==1&&$7>20000{print}
仅打印第二个字段==1和7nt字段>2000的行

调试脚本示例:

BEGIN{FS="[ ]*[_]?"}
{
    for(i = 1; i <= NF; i++) printf("$%d=%s%s",i, $i, OFS);
    print "";
}
$2==1 && $7 > 20000 {print}
得出结论:

结论:为了避免处理引用问题,只需编写一个小脚本或函数(记住导出函数-f)并让GNU并行调用它,可能会更容易

因此:

得出结论:

结论:为了避免处理引用问题,只需编写一个小脚本或函数(记住导出函数-f)并让GNU并行调用它,可能会更容易

因此:


不考虑并行,但你不必使用两个awk,你可以让
空白
作为awk的FS。我尝试了这个
awk-F“”$1=$1'{if($2==1&$3>20000){print}}
,但是这两个awk都不起作用,因为与parallel和awk之间的一些交互相比,使用存储在变量中的awk脚本更有可能成为问题。您是否尝试过不并行地执行
zcat{}|awk'$awk1'| awk'$awk2'
?怎么样?一旦你将变量周围的引号改为双引号而不是单引号,让它们展开,那么它是如何进行的呢?一旦你迭代地修复了这些问题,然后试着用parallel运行它。同意上面的评论,但是你评论说我尝试了这个awk-F““'$1=$1”。。你的意思是像你上面的代码那样,
$2==1
?祝你好运。@EdMorton,你说得对。没有并行的awk'$awk1'也不起作用。关于并行,但你不必使用两个awk,你可以让
whitespaces
作为awk的FS。我尝试了这个
awk-F“'$1=$1'{if($2==1&$3>20000){print}},但是这两个awk都不起作用,因为与parallel和awk之间的一些交互相比,使用存储在变量中的awk脚本更有可能成为问题。您是否尝试过不并行地执行
zcat{}|awk'$awk1'| awk'$awk2'
?怎么样?一旦你将变量周围的引号改为双引号而不是单引号,让它们展开,那么它是如何进行的呢?一旦你迭代地修复了这些问题,然后试着用parallel运行它。同意上面的评论,但是你评论说我尝试了这个awk-F““'$1=$1”。。你的意思是像你上面的代码那样,
$2==1
?祝你好运。@EdMorton,你说得对。没有平行线的awk“$awk1”也不起作用。
$1=gene $2=id $3=variant $4=id $5=tss $6=distance $7=ma $8=samples $9=ma $10=count $11=maf $12=pval $13=nominal $14=slope $15=slope $16=se 
$1=ENSG00000223972.4 $2=1 $3=13417 $4=C $5=CGAGA $6=b37 $7=1548 $8=50 $9=50 $10=0.0766871 $11=0.735446 $12=-0.0468165 $13=0.138428 
$1=ENSG00000223972.4 $2=1 $3=17559 $4=G $5=C $6=b37 $7=5690 $8=7 $9=7 $10=0.00964187 $11=0.39765 $12=-0.287573 $13=0.339508 
$1=ENSG00000223972.4 $2=1 $3=54421 $4=A $5=G $6=b37 $7=42552 $8=28 $9=28 $10=0.039548 $11=0.680357 $12=0.0741142 $13=0.179725 
ENSG00000223972.4   1_54421_A_G_b37 42552   28  28  0.039548    0.680357    0.0741142   0.179725
$1=ENSG00000223972.4 $2=1 $3=54490 $4=G $5=A $6=b37 $7=42621 $8=112 $9=120 $10=0.176471 $11=0.00824733 $12=0.247533 $13=0.093081 
ENSG00000223972.4   1_54490_G_A_b37 42621   112 120 0.176471    0.00824733  0.247533    0.093081
doit() {
  zcat "$1" |
    awk -F "_"  '$1=$1' |
    awk '{if ($2==1 && $3>20000) {print}}'
}
export -f doit
parallel 'doit {} > {=s/In/Out/; s/.gz//=}' ::: InputData*.txt.gz