查找一个文件在另一个文件范围内的值并选择顶部值

查找一个文件在另一个文件范围内的值并选择顶部值

我有两个文件 A 和 B。文件 A 有 4 列和 600,000 行。文件 B 有 4 列和 5000 行。例子:

文件-A:

ENSB1 1 12245 0.53 0.002
ENSB2 1 13400 0.27 0.0003
ENSB3 1 14780 0.13 0.00001
ENSB4 1 15201 0.33 0.9
ENSB5 2 56259 0.70 0.0002
ENSB6 2 57000 0.42 0.00004
ENSB7 2 58200 0.50 0.5

文件-B:

1 12000 15000 G1
1 14000 16000 G2
2 56000 59000 G3

我想选择 File-B 的第一行。然后,我想以文件 A 第 3 列中的值落在文件 B 第 2 列和第 3 列中的值范围内的方式识别文件 A 中的多行;文件 A 第 2 列中的对应值也与文件 B 第 1 列中的值匹配。我期望 File-A 中的多行满足上述条件。一旦通过上述标准识别出多行,则在文件 A 的这些行中选择第 5 列中的最低值,并将其写入文件 B 中相应行的新列中。对 File-B 中的所有行一一重复这些步骤。

预期新文件:

1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004

我是学习 Linux 命令的新手,如果有人能提供帮助,那就太好了。

答案1

尝试

awk 'NR==FNR   {Line[FNR] = $0           # first file processing
                Cat[FNR]  = $1
                Min[FNR]  = $2
                Max[FNR]  = $3
                Low[FNR]  = 1E10         # initialize to high number so first value from file2 will be lower
                ML        = FNR
                next
               }
                                         # second file processing; if same Category and $3 between Min and Max, and $5 lower than before one, keep $5

               {for (i=1; i<=ML; i++)  if ($2 == Cat[i] &&
                                           $3 >= Min[i] &&
                                           $3 <= Max[i] &&
                                           $5 <  Low[i]) Low[i] = $5
               }
END                     {for (i=1; i<=ML; i++) print Line[i], Low[i]
                        }
' File-B File-A
1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004

不需要太多解释:从第一个文件 ( NR == FNR) 开始,它保留类别和范围/边界值,并设置 Low 数组元素,以便第一个读取的实际值较低。处理第二个文件时,它会循环遍历上述记录的数据集。如果新读取的记录与条目具有相同的类别,并且 $3 在 Min 和 Max 之间,并且 $5 比之前获得的记录低,则将 $5 保留在数组中Low。在该END部分中,将记录的行及其获得的Low值打印到标准输出。

答案2

使用任何awk和任何sort

$ cat tst.sh
#!/usr/bin/env bash

sort -k5,5n -- "$1" |
awk '
NR==FNR {
    if ( !($3 in map) ) {
        keys[++numKeys] = $3
        map[$3] = $5
    }
    next
}
{
    for ( k=1; k<=numKeys; k++ ) {
        key = keys[k]
        if ( ($2 <= key) && (key <= $3) ) {
            print $0, map[key]
            next
        }
    }
}
' - "$2"

$ ./tst.sh 'File-A' 'File-B'
1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004

当出现重复的 $3 值时,上面将正确使用最低的关联 $5 File-A

相关内容