Bash 如何基于从第二个文件中获取的值范围排除文件中的行
我有一个包含值范围列表的文件:Bash 如何基于从第二个文件中获取的值范围排除文件中的行,bash,awk,grep,cut,Bash,Awk,Grep,Cut,我有一个包含值范围列表的文件: 2 4 6 9 13 14 第二个文件如下所示: HiC_scaffold_1 1 26 HiC_scaffold_1 2 27 HiC_scaffold_1 3 27 HiC_scaffold_1 4 31 HiC_scaffold_1 5 34 HiC_scaffold_1 6 35 HiC_scaffold_1 7 37 HiC_scaffold_1 8 37 HiC_scaffold_1
2 4
6 9
13 14
第二个文件如下所示:
HiC_scaffold_1 1 26
HiC_scaffold_1 2 27
HiC_scaffold_1 3 27
HiC_scaffold_1 4 31
HiC_scaffold_1 5 34
HiC_scaffold_1 6 35
HiC_scaffold_1 7 37
HiC_scaffold_1 8 37
HiC_scaffold_1 9 38
HiC_scaffold_1 10 39
HiC_scaffold_1 11 39
HiC_scaffold_1 12 39
HiC_scaffold_1 13 39
HiC_scaffold_1 14 39
HiC_scaffold_1 15 42
我想从文件2中排除第2列的值在文件1定义的范围内的行。理想的输出是:
HiC_scaffold_1 1 26
HiC_scaffold_1 5 34
HiC_scaffold_1 10 39
HiC_scaffold_1 11 39
HiC_scaffold_1 12 39
HiC_scaffold_1 15 42
我知道如何使用awk提取单个范围:
awk'$2==2,$2==4'file2.txt
但是我的文件1有许多范围值行,我需要排除而不是提取与这些值对应的行。这是一个错误:
$ awk '
NR==FNR { # first file
min[NR]=$1 # store mins and maxes in pairs
max[NR]=$2
next
}
{ # second file
for(i in min)
if($2>=min[i]&&$2<=max[i])
next
}1' ranges data
如果范围不是很大且是整数值,但数据很大,则可以制作值的排除映射以加快比较:
$ awk '
NR==FNR { # ranges file
for(i=$1;i<=$2;ex[i++]); # each value in the range goes to exclude hash
next
}
!($2 in ex)' ranges data # print if not found in ex hash
这是一个错误:
$ awk '
NR==FNR { # first file
min[NR]=$1 # store mins and maxes in pairs
max[NR]=$2
next
}
{ # second file
for(i in min)
if($2>=min[i]&&$2<=max[i])
next
}1' ranges data
如果范围不是很大且是整数值,但数据很大,则可以制作值的排除映射以加快比较:
$ awk '
NR==FNR { # ranges file
for(i=$1;i<=$2;ex[i++]); # each value in the range goes to exclude hash
next
}
!($2 in ex)' ranges data # print if not found in ex hash
催眠
如果file2.txt的第二列始终等于其行的索引,则可以使用sed修剪这些行。如果不是您的情况,请参考AWK概念段落
sed$sed's/^\[0-9]*\[:space:]*\[0-9]*\/-e\1、\2d/'file1.txt file2.txt
其中file1.txt包含您的范围,file2.txt是数据本身
基本上,它构造了一个sed调用,链接了一个-ei,jd表达式列表,这意味着它将删除第i行和第j行之间的行
在您的示例中,sed的/^\[0-9]*\[:space:]*\[0-9]*\/-e\1、\2d/'file1.txt将输出-e2,4d-e6,9d-e13,14d,这是在file2.txt上调用sed的表达式列表
最后它将呼吁:
sed-e2,4d-e6,9d-e13,14d文件2.txt
此命令删除第2行和第4行之间的所有行,第6行和第9行之间的所有行,以及第13行和第14行之间的所有行
显然,如果file2.txt的第二列与其自身行的索引不匹配,那么它就不起作用
AWK观念
awk{$awk'{printf如果$2>=%d&&$2sedException
如果file2.txt的第二列始终等于其行的索引,则可以使用sed删除行。如果不是这样,请参阅awkception段落
sed$sed's/^\[0-9]*\[:space:]*\[0-9]*\/-e\1、\2d/'file1.txt file2.txt
其中file1.txt包含您的范围,file2.txt是数据本身
基本上,它构造了一个sed调用,链接了一个-ei,jd表达式列表,这意味着它将删除第i行和第j行之间的行
在您的示例中,sed的/^\[0-9]*\[:space:]*\[0-9]*\/-e\1、\2d/'file1.txt将输出-e2,4d-e6,9d-e13,14d,这是在file2.txt上调用sed的表达式列表
最后它将呼吁:
sed-e2,4d-e6,9d-e13,14d文件2.txt
此命令删除第2行和第4行之间的所有行,第6行和第9行之间的所有行,以及第13行和第14行之间的所有行
显然,如果file2.txt的第二列与其自身行的索引不匹配,那么它就不起作用
AWK观念
awk{$awk'{printf如果$2>=%d&&$2如果范围不大:
$ cat tst.awk
NR==FNR {
for (i=$1; i<=$2; i++) {
bad[i]
}
next
}
!($2 in bad)
$ awk -f tst.awk file1 file2
HiC_scaffold_1 1 26
HiC_scaffold_1 5 34
HiC_scaffold_1 10 39
HiC_scaffold_1 11 39
HiC_scaffold_1 12 39
HiC_scaffold_1 15 42
如果您的范围不大:
$ cat tst.awk
NR==FNR {
for (i=$1; i<=$2; i++) {
bad[i]
}
next
}
!($2 in bad)
$ awk -f tst.awk file1 file2
HiC_scaffold_1 1 26
HiC_scaffold_1 5 34
HiC_scaffold_1 10 39
HiC_scaffold_1 11 39
HiC_scaffold_1 12 39
HiC_scaffold_1 15 42
看起来第二列等于其行的索引。总是这样吗?看起来第二列等于其行的索引。总是这样吗?效果很好,但不幸的是,我的一些数据文件长度超过4000万行,相应的范围文件长度超过100000行,这在se环境。这在您的问题中是值得说明的。效果很好,但不幸的是,我的一些数据文件长度超过4000万行,相应的范围文件长度超过100000行,在这种情况下,这很困难。这在您的问题中是值得说明的。排除散列非常有效。在较大的文件上运行时占用了2gb内存,但这是完全可以接受的。排除散列运行得非常出色。在较大的文件上运行时占用了2gb内存,但这是完全可以接受的。