仅使用匹配项,如果列值在文件B中的其他两个列值之间,则打印文件A行

时间:2019-06-21 20:14:15

标签: awk

我有一个制表符delim文件1

A 1
A 20
B 17
B 33
C 10
C 20
E 7

和另一个标签delim文件2

A 1  5
A 6  20
B 1  10
B 30 60
C 10 20
E 1  6

我需要打印file1中col1 file1 = col1 file2并且col2 file1中的值在file2 cols 2和3范围内的行。

输出看起来像

A 1
A 20
B 33
C 10
C 20

我正在尝试

awk 'FNR==NR{a[$1]=$2;next}; ($1) in a{if($2=(a[$1] >= $2 && a[$1] <=$3) {print}}1'  file1  file2 

但是它不起作用。

2 个答案:

答案 0 :(得分:0)

要存储多个范围,您确实要使用数组数组或列表。 awk不直接支持它们,但是可以对其进行仿真。在这种情况下,数组的数组似乎更有效率。

awk '
    # store each range from file2
    FNR==NR {
        n = ++q[$1]
        min[$1 FS n] = $2
        max[$1 FS n] = $3
        next
    }

    # process file1
    n = q[$1] { # if no q entry, line cannot be in range
        for (i=1; i<=n; i++)
            if ( min[$1 FS i]<=$2 && $2<=max[$1 FS i]) {
                print
                next
            }
    }
' file2 file1

答案 1 :(得分:0)

我对此的绝望解决方案是使用一些基本的awk操作将我的file2操纵到其中

A 1 gene_starts
A 5 gene_ends
A 6 gene_starts
A 20 gene_ends
B 1 gene_starts
B 10 gene_ends
B 30 gene_starts
B 60 gene_ends
C 10 gene_starts
C 20 gene_ends
E 1 gene_starts
E 6 gene_ends

因此,我可以对两个文件1和2进行排序,并在gene_starts和genes_ends之间抓线

sort -V -k1,2 file1 file2 | awk '/gene_starts/,/gene_ends/' | awk '!length($3)' 

但这让我只能得到

A 20
B 33
C 20

因为排序将来自file1的匹配gene_start的行放在它们之前。 因此,要获得A 1和C 10,我必须从file2中过滤出gene_ends并使用

awk 'NR==FNR{c[$1,$2];next} (($1,$2) in c)' file2 file1

获得也位于file1中的gene_starts行,然后将其添加到我的输出中