首页 > 解决方案 > 如果pattern匹配两行,如何融合两行的信息?

问题描述

我想融合两行的信息,如果第二列和第三列的坐标重叠并且第一列是相同的。

输入:

chr1    2   29  tcttttcagtgtctttagatgtgtact,
chr1    30  55  agcacatgattagaagctaccaatgg,
chr1    33  58  acatgattagaagctaccaatggccc,
chr2    30  52  ctaggcttacagaagtgagccc,

输出:

chr1    2   29  tcttttcagtgtctttagatgtgtact,
chr1    30  58  agcacatgattagaagctaccaatggccc,
chr2    30  52  ctaggcttacagaagtgagccc,

输出的第二行覆盖输入的第 2 行和第 3 行的跨度,从 30(从第 2 行开始)到 58(从第 3 行开始)(当条件为真时,坐标与第 1 列重叠是相等的)。每个坐标都链接到第 4 列的对应字母。对于输入的第二行:

30 31 32 33 34 35 36 ... 50 51 52 53 54 55
a  g  c  a  c  a  t  ... c  a  a  t  g  g

所以如果融合了坐标,那么第4列的信息也应该融合。在这种情况下,最后添加了三个字母:

30 31 32 33 34 35 36 ... 50 51 52 53 54 55 56 57 58
a  g  c  a  c  a  t  ... c  a  a  t  g  g  c  c  c

我试图每 2 行减去第 2 列,并删除第 2 列中包含相似值的行。但我不知道如何融合信息。

awk 'NR-1{print $2-p}{p=$2}1' input.txt | paste - - | awk '($5>BiggerAs || $5<-SmallerAs)'

标签: awk

解决方案


OP评论中的假设和细节收集:

  • 列 2/3 是开始/结束索引(分别)表示来自染色体序列的子字符串
  • 第 4 列是染色体序列的实际子串
  • 数据已经排序
  • 目标是合并相关索引重叠的子字符串(例如,在 OP 的示例数据中,我们需要合并第 2 行和第 3 行)
  • 如果重叠的子字符串在同一位置具有不同的值,则第一个值将被捕获/存储为“正确”值(即,我们不会验证重叠位置是否相同)

方法:

  • 使用第 2/3 列中的值作为稀疏数组的索引,其中每个数组元素都是一个字母
  • 对于重叠的子字符串,我们将那些尚未看到的位置/字母添加到数组中

使用 OP 的原始样本数据集:

$ cat input.txt
chr1    196308345   196308372   tcttttcagtgtctttagatgtgtact,
chr1    63095765    63095788    agcacatgattagaagctaccaatg
chr1    63095768    63095791    acatgattagaagctaccaatgccc,
chr2    63095768    63095789    ctaggcttacagaagtgagcc,

一种awk解决方案:

awk '

function print_seq()                                        # function to print the merged data
{
  if ( seqend == 0 )                                        # make sure we have something to print; "seqend == 0" => we haven't processed any data, yet
     return

  printf "%-7s %-11s %-11s ", prev1, seqstart, seqend       # print first 3 columns

  for (i in myseq)                                          # print merged substring
      printf "%s",myseq[i]

  printf ",\n"                                              # print trailing comma + linefeed
}

function reset_ends()                                       # function to reset our start/end indices
{
  seqstart = 2^PREC
  seqend   = 0
}

BEGIN         { reset_ends() }                              # (re)set our indices

# if field 1 has changed or columns 2 & 3 are outside the previously seen index range then
# print the last substring and reset some variables

prev1 != $1 ||
$2 > seqend ||
$3 < seqstart { print_seq()                                 # print the last seq ...
                reset_ends()                                # reset our indices ...
                delete myseq                                # delete array containing last overlapping substring ...
                prev1=$1                                    # reset our "previous field 1" tracker
              }

# process a new, or overlapping, substring

              { seqstart = $2 < seqstart ? $2 : seqstart    # new/lesser sequence start?
                seqend   = $3 > seqend   ? $3 : seqend      # new/greater sequence end?
                j=$2                                        # initial index for myseq[] array

                gsub(",","",$4)                             # remove commas (eg, trailing comma)
                n=split($4,arr,"")                          # split column 4 into array of single-letter elements; "n" == number of elements in array

                for (i=1; i<=n; i++)                        # loop through our new set of letters
                    if ( j in myseq )                       # if we have already seen a letter for position "j" ...
                       j++                                  # increment j otherwise ...
                    else
                       myseq[j++]=arr[i]                    # add this new letter to our merged substring
              }

END           { print_seq() }                               # print last substring

' input.txt

以上生成:

chr1    196308345   196308372   tcttttcagtgtctttagatgtgtact,
chr1    63095765    63095791    agcacatgattagaagctaccaatgccc,
chr2    63095768    63095789    ctaggcttacagaagtgagcc,

另一种方法(对于要合并的行)将使用索引差异来仅提取新的第 4 列字符串的“未见”部分(例如,通过substring()函数)并在之前看到的第 4 列字符串之前添加/附加。


推荐阅读