Sed 如果行文件1中的数字介于文件2中的两个数字之间,则合并两个文件中的特定行

Sed 如果行文件1中的数字介于文件2中的两个数字之间,则合并两个文件中的特定行,sed,merge,awk,genome,Sed,Merge,Awk,Genome,我搜索了几个小时(实际上已经两天了),但我还找不到问题的答案。我尝试过Sed和Awk,但无法获得正确的参数 基本上,这就是我要找的 对于文件_1中的每一行 如果[文件_1中以列2表示的值] 等于[文件_2中某行第4列中的值] 或等于[文件_2中某行第5列中的值] 或者介于[文件_2中某行的值列4和值列5]之间 比 将文件_2某行的第3、6和7列添加到文件_1的第3、4和5列 注意:需要比较的值是整数,第3列、第6列和第7列中的值(只需要复制)是字符串 这是上下文,但可能不需要阅读: 我有两个包

我搜索了几个小时(实际上已经两天了),但我还找不到问题的答案。我尝试过Sed和Awk,但无法获得正确的参数

基本上,这就是我要找的

对于文件_1中的每一行
如果[文件_1中以列2表示的值]
等于[文件_2中某行第4列中的值]
或等于[文件_2中某行第5列中的值]
或者介于[文件_2中某行的值列4和值列5]之间

将文件_2某行的第3、6和7列添加到文件_1的第3、4和5列

注意:需要比较的值是整数,第3列、第6列和第7列中的值(只需要复制)是字符串

这是上下文,但可能不需要阅读:


我有两个包含基因组数据的文件,我想以一种特定的方式合并它们(列是用制表符分隔的)

  • 第一个文件包含变体(只有感兴趣的SNP),有效地,只有第二列与之相关。此列是数字列表(该变体在染色体上的位置)
  • 我有一个包含以下数据的结构注释文件:
    • 第4列是特定结构的开始位置,第5列是结束位置
    • 第3、7和9列包含描述特定结构(基因名称等)的信息
我想用注释文件中的数据注释第一个文件中的变量。因此,如果变体文件第2列中的数字等于第4列或第5列,或在特定行中的值之间,则需要在注释中添加该特定行的第3、7和9列


示例文件1

SOME_NON_RELEVANT_STRING    142
SOME_NON_RELEVANT_STRING    182
SOME_NON_RELEVANT_STRING    320
SOME_NON_RELEVANT_STRING    321
SOME_NON_RELEVANT_STRING    322
SOME_NON_RELEVANT_STRING    471
SOME_NON_RELEVANT_STRING    488
SOME_NON_RELEVANT_STRING    497
SOME_NON_RELEVANT_STRING    541
SOME_NON_RELEVANT_STRING    545
SOME_NON_RELEVANT_STRING    548
SOME_NON_RELEVANT_STRING    4105
SOME_NON_RELEVANT_STRING    15879
SOME_NON_RELEVANT_STRING    26534
SOME_NON_RELEVANT_STRING    30000
SOME_NON_RELEVANT_STRING    30001
SOME_NON_RELEVANT_STRING    40001
SOME_NON_RELEVANT_STRING    44752
SOME_NON_RELEVANT_STRING    50587
SOME_NON_RELEVANT_STRING    87512
SOME_NON_RELEVANT_STRING    96541
SOME_NON_RELEVANT_STRING    99541
SOME_NON_RELEVANT_STRING    99871
示例文件2

SOME_NON_RELEVANT_STRING    SOME_NON_RELEVANT_STRING    A1  0   38  B1  C1
SOME_NON_RELEVANT_STRING    SOME_NON_RELEVANT_STRING    A2  40  2100    B2  C2
SOME_NON_RELEVANT_STRING    SOME_NON_RELEVANT_STRING    A3  2101    9999    B3  C3
SOME_NON_RELEVANT_STRING    SOME_NON_RELEVANT_STRING    A4  10000   15000   B4  C4
SOME_NON_RELEVANT_STRING    SOME_NON_RELEVANT_STRING    A5  15001   30000   B5  C5
SOME_NON_RELEVANT_STRING    SOME_NON_RELEVANT_STRING    A6  30001   40000   B6  C6
SOME_NON_RELEVANT_STRING    SOME_NON_RELEVANT_STRING    A7  40001   50001   B7  C7
SOME_NON_RELEVANT_STRING    SOME_NON_RELEVANT_STRING    A8  50001   50587   B8  C8
SOME_NON_RELEVANT_STRING    SOME_NON_RELEVANT_STRING    A9  50588   83054   B9  C9
SOME_NON_RELEVANT_STRING    SOME_NON_RELEVANT_STRING    A10 83055   98421   B10 C10
SOME_NON_RELEVANT_STRING    SOME_NON_RELEVANT_STRING    A11 98422   99999   B11 C11
示例输出文件

142 A2  B2  C2
182 A2  B2  C2
320 A2  B2  C2
321 A2  B2  C2
322 A2  B2  C2
471 A2  B2  C2
488 A2  B2  C2
497 A2  B2  C2
541 A2  B2  C2
545 A2  B2  C2
548 A2  B2  C2
4105    A3  B3  C3
15879   A5  B5  C5
26534   A5  B5  C5
30000   A5  B5  C5
30001   A6  B6  C6
40001   A7  B7  C7
44752   A7  B7  C7
50587   A8  B8  C8
87512   A10 B10 C10
96541   A10 B10 C10
99541   A11 B11 C11
99871   A11 B11 C1

1

首先,这里介绍如何编写您在awk中发布的算法,假设您说的“添加”是指“附加”,并且假设file1中的所有行都具有第二个字段的唯一值(根据提供的示例输入运行):

awk'
开始{FS=OFS=“\t”;startIdx=1}
NR==FNR{
若有(见表2美元){
printf“%s在第%d行上,第一次出现在第%d行\n上,$2,NR,出现[$2]|“cat>&2”
}
否则{
f2s[++endIdx]=2美元
已见[$2]=NR
}
下一个
}
{
内边界=1
对于(idx=startIdx;(idx=4美元){

如果(f2)当你加入一堆特定领域的语言(SNP、基因组、染色体上的变体等),我们就很难弄清楚你想要什么。只需发布平面文件(未格式化),然后说“文件1中给定的值X,如果值Y或Z出现在文件2的字段a中,我想输出两个文件中的任何字段”.Ha好的,非常感谢。我编辑了我的帖子,并添加了几行内容,以一种更常见的方式总结了整个故事。希望它更容易理解。是的,但您仍然没有发布一些示例输入和预期输出,我们可以简单地复制/粘贴以测试解决方案。我个人不打算复制您发布的那些表并编辑它们再次感谢Ed,非常感谢。我创建了一个示例文件1、文件2和输出文件。非常感谢!我更新了我的答案,并针对您发布的示例输入运行了它,它生成了您想要的输出,请参见下文。这太棒了!是的,确实,使用ADD,我是指append。在一个完美的世界中,中没有任何值文件_1应该出现不止一次。但是,DNA测序器远不是完美的,有时会产生不可能的数据,所以会有一些噪音。但是我可以在脚本之前过滤掉它。我现在正在我更大的数据集上运行脚本,并会让你知道结果!已经感谢了一千次!不客气。我刚刚更新了我的答案是告诉第一个文件中的值是否/何时被复制,以及复制发生的行号。再次感谢!它现在正在我的数据集上运行,但有点慢。根据平均速度,完成大约需要48小时。此外,它只使用16个可用内核中的一个,所以我要做的第一件事是tomorrow正在将文件1拆分为16个部分,并启动16个AWK实例。或者在AWK中有更简单的选项吗?我修改了算法,使其更有效,因为您的两个文件都已排序,并且文件2具有不同的范围。它现在只在文件1字段2值上循环,从前面文件2边界内的位置开始$4-$5值,而不是总是从第一个值开始,并且当您遇到超过当前file2 field 5值的file1 field 2值时退出循环。这应该会显著提高性能,但检查逻辑-我没有测试过它,甚至没有过多考虑过它,但希望您能了解这个想法,并在必要时修复/改进它ssary.@Elmer仅供参考,您可以使用分割输入,并针对分割的块并行运行脚本。
awk '
BEGIN{ FS=OFS="\t"; startIdx=1 }
NR==FNR {
    if ($2 in seen) {
         printf "%s on line %d, first seen on line %d\n", $2, NR, seen[$2] | "cat>&2"
    }
    else {
         f2s[++endIdx] = $2
         seen[$2] = NR
    }
    next
}
{
    inBounds = 1
    for (idx=startIdx; (idx<=endIdx) && inBounds; idx++) {
        f2 = f2s[idx]
        if (f2 >= $4) {
            if (f2 <= $5) {
                print f2, $3, $6, $7
            }
            else {
                inBounds = 0
            }
        }
        else {
            startIdx = idx
        }
    }
}
' file1 file2
142     A2      B2      C2
182     A2      B2      C2
320     A2      B2      C2
321     A2      B2      C2
322     A2      B2      C2
471     A2      B2      C2
488     A2      B2      C2
497     A2      B2      C2
541     A2      B2      C2
545     A2      B2      C2
548     A2      B2      C2
4105    A3      B3      C3
15879   A5      B5      C5
26534   A5      B5      C5
30000   A5      B5      C5
30001   A6      B6      C6
40001   A7      B7      C7
44752   A7      B7      C7
50587   A8      B8      C8
87512   A10     B10     C10
96541   A10     B10     C10
99541   A11     B11     C11
99871   A11     B11     C11