unix 尝试将合并awk和zcat与多个过滤标准相结合

uhry853o  于 2023-11-18  发布在  Unix
关注(0)|答案(1)|浏览(138)

我有非常大的文件(40米x400列)。
结构如:

chr  pos  snp
1   1   rs500
2   4   rs501
2   6   rs502
17   6   rs503

字符串
给定名称myfile.gz
要搜索第三列中的给定值,请执行以下操作:

zcat myfile | grep rs500$


然而,为了搜索两个条件-比如chr = 17pos = 6,我试图执行以下操作,但无法使其返回值。

zcat myfile | awk '{ if ($1 == 17 && $2 == 6) print }'


没有错误,但没有返回任何东西。我在过去做过这种过滤,当文件不是.gz压缩时,没有问题。
例如在一个更大的不同文件中的此命令,该文件根据条件筛选两列,然后检索结果。

"awk '{ if (NR == 1 || ($39  >= 0.03 && $36 <= 1e-04)) print }' myfile.notgzcompressed"


但我似乎不能将该语法与zcat的需要结合起来,因为我不想解压缩我的庞大归档

EDIT to add information based on comments
zcat myfile.gz | head -2 | od -c
0000000   c   h   r  \t   p   o   s  \t   r   e   f  \t   a   l   t  \t
0000020   c   h   r   _   h   g   1   9  \t   p   o   s   _   h   g   1
0000040   9  \t   r   e   f   _   h   g   1   9  \t   a   l   t   _   h
0000060   g   1   9  \t   V   E   P   _   e   n   s   e   m   b   l   _
0000100   s   u   m   m   a   r   y  \t   r   s   _   d   b   S   N   P
0000120   1   5   1  \n   1  \t   1   0   1   8   0  \t   T  \t   C  \t
0000140   1  \t   1   0   1   8   0  \t   T  \t   C  \t   W   A   S   H
0000160   7   P   (   1   )   :   d   o   w   n   s   t   r   e   a   m
0000200   _   g   e   n   e   _   v   a   r   i   a   n   t   (   1   )
0000220   |   D   D   X   1   1   L   1   (   2   )   :   u   p   s   t
0000240   r   e   a   m   _   g   e   n   e   _   v   a   r   i   a   n
0000260   t   (   2   )  \t   r   s   2   0   1   6   9   4   9   0   1
0000300  \n


更多信息,我使用R和fread()来传递这样的命令,以便unix在加载到R环境之前进行解析。

fread(cmd = paste0("zcat ", myfile, " | awk ","'{ if ($1  == ", chr ," && $2 == ",pos,") print }'")) -> h2

zzwlnbp8

zzwlnbp81#

我怀疑在使用

zcat myfile | awk '{ if ($1 == 17 && $2 == 6) print }'

字符串
如果|有巨大的myfile问题可能会出现在|.即|有有限的机器依赖的容量(进一步阅读The Pipe Buffer Capacity in Linux),如果你的awk没有足够快地读取|可能会成为挤满了数据.
如果你的数据从来没有前导零,并且有一个由单个TAB字符分隔的字段,并且你对第一个字段等于值而第二个字段等于值感兴趣,那么你可以使用GNU grep来完成这个任务,第一个字段包含17,第二个字段包含6,可以用下面的方式表示,假设你有command,它产生TAB分隔的输出

chr pos snp
1   1   rs500
2   4   rs501
2   6   rs502
17  6   rs503
17  600 rs504


然后

command | grep -P --color=never '^17\t6\b'


给出输出

17  6   rs503


说明:我指示GNUgrep使用perl-flavor正则表达式,并且不要用转义序列污染输出,并查找以(^17后跟TAB字符,后跟6,跨越到字边界(\b)-为了防止抓取第二列以6开始但不是6的行(观察command输出的最后一行)。

  • (在GNU grep 3.7中测试)*

相关问题