首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何根据从第二个文件中提取的值范围排除文件中的行

如何根据从第二个文件中提取的值范围排除文件中的行
EN

Stack Overflow用户
提问于 2020-03-06 15:13:42
回答 3查看 230关注 0票数 1

我有一个包含值范围列表的文件:

代码语言:javascript
复制
2    4
6    9
13   14

第二个文件是这样的:

代码语言:javascript
复制
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定义的范围内的行。理想的输出是:

代码语言:javascript
复制
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有许多范围值(行),我需要排除而不是提取与这些值相对应的行。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-03-06 15:24:24

这是一个可怕的问题:

代码语言:javascript
复制
$ 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

输出:

代码语言:javascript
复制
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

如果范围和整数值不是很大,但数据很大,则可以对值进行排除映射,以加快比较速度:

代码语言:javascript
复制
$ 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
票数 3
EN

Stack Overflow用户

发布于 2020-03-06 21:01:34

如果你的范围不是很大:

代码语言:javascript
复制
$ 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
票数 1
EN

Stack Overflow用户

发布于 2020-03-06 17:40:43

坐席

如果file2.txt的第二列总是等于其行的索引,则可以使用sed来修剪行。如果这不是您的情况,请参阅尴尬段落。

代码语言:javascript
复制
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的第二列与它自己行的索引不匹配,它就不能工作。

尴尬感

代码语言:javascript
复制
awk "{$(awk '{printf "if ($2>=%d && $2<=%d) next\n", $1, $2}' file1.txt)}1" file2.txt

即使第二列与其行的索引不匹配,此解决方案也能工作。

该方法使用awk创建一个awk程序,就像sedsedception解决方案中创建sed表达式一样。

到头来,这将要求:

代码语言:javascript
复制
awk '{
if ($2>=2 && $2<=4) next
if ($2>=6 && $2<=9) next
if ($2>=13 && $2<=14) next
}1' file2.txt

应该注意的是,这个解决方案比sed慢得多。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60566879

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档