我有一个包含值范围列表的文件:
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有许多范围值(行),我需要排除而不是提取与这些值相对应的行。
发布于 2020-03-06 15:24:24
这是一个可怕的问题:
$ 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输出:
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 '
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发布于 2020-03-06 21:01:34
如果你的范围不是很大:
$ 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发布于 2020-03-06 17:40:43
坐席
如果file2.txt的第二列总是等于其行的索引,则可以使用sed来修剪行。如果这不是您的情况,请参阅尴尬段落。
sed $(sed 's/^\([0-9]*\)[[:space:]]*\([0-9]*\)/-e \1,\2d/' file1.txt) file2.txt其中file1.txt包含您的范围,file2.txt是数据本身。
基本上,它构造一个sed调用,该调用链接一个-e i,jd表达式列表,这意味着它将删除ith行和jth行之间的行。
在您的示例中,sed 's/^\([0-9]*\)[[:space:]]*\([0-9]*\)/-e \1,\2d/' file1.txt将输出-e 2,4d -e 6,9d -e 13,14d,这是用于在file2.txt上调用sed的表达式列表。
最后,它将呼吁:
sed -e 2,4d -e 6,9d -e 13,14d file2.txt
此命令删除第2至第4段之间的所有行,第6至第9段之间的所有行,以及13至14段之间的所有行。
显然,如果file2.txt的第二列与它自己行的索引不匹配,它就不能工作。
尴尬感
awk "{$(awk '{printf "if ($2>=%d && $2<=%d) next\n", $1, $2}' file1.txt)}1" file2.txt即使第二列与其行的索引不匹配,此解决方案也能工作。
该方法使用awk创建一个awk程序,就像sed在sedception解决方案中创建sed表达式一样。
到头来,这将要求:
awk '{
if ($2>=2 && $2<=4) next
if ($2>=6 && $2<=9) next
if ($2>=13 && $2<=14) next
}1' file2.txt应该注意的是,这个解决方案比sed慢得多。
https://stackoverflow.com/questions/60566879
复制相似问题