当行ID匹配时,如果子字符串中存在另一个文件中的两个字符位置,则从文件中提取子字符串

时间:2019-07-23 15:25:14

标签: awk

我有一个带有标识符(ID)和两个位置编号的文件。在实际文件中,有12列,并且相关位置位于字段7和8中,但是为了清楚起见,我从示例文件1中删除了该信息:

ID1   1   18
ID2   5   12
ID3   9   24
ID2   7   14

第二个文件包含我感兴趣的字符串。行具有与file1相同的标识。 file2:

ID1   abcdefghijklmnopqr*stuvw**xyz
ID2   ab*cdefghijklmno*pqrst*uvwxyz
ID3   *abcd*efghi*jklmnopqrs*tuvwxyz
ID4   abcde*fgh*ijklmnopq*rstuvwxyz*

在这种情况下,字段2中的字符串本身由星号(*)分隔为较小的子字符串。在这种情况下,子字符串定义为字段开始和星号之间,两个星号之间,星号和字段结尾之间或字段开始/结尾之间的任何字符串。

我想做的是,如果文件之间的ID匹配,并且file1中的两个位置都对应于出现在file2中同一子字符串中的字符,请将整个子字符串追加到file1中,不包括星号。所需的输出:

ID1   1   18   abcdefghijklmnopqr
ID2   5   12   cdefghijklmno
ID3   9   24   
ID2   7   14   cdefghijklmno

说明:

  • 对于ID1,字符串中的位置1对应于“ a”,它也是子字符串的第一个字母。位置18对应于“ r”,它也是子字符串的最后一个字母,因此打印位置1-18就足够了。
  • 但是对于第一次出现的ID2,字符串中的位置5对应于d,它不是子字符串的第一个字母。位置12也不是子字符串的最后一个字母(k处于位置12)。尽管如此,仍应打印整个子字符串(从c到o)。
  • 对于ID3,位置9和24位于不同的子字符串中,因此不应打印任何子字符串。
  • 对于ID2的第二次出现,与第一次出现相同,提供了此示例以说明ID可以多次出现。

字符串可以以星号开头和/或结尾,随后可以出现多个星号,并且字符串也可以完全没有星号。 file2中有一些ID在file1中没有。每个ID中File1可以包含多行,每个ID中file2仅包含一行。

希望我能明确我的问题。我对此还很陌生,感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

$ cat tst.awk
NR==FNR {
    beg[$1] = $2
    end[$1] = $3
    next
}
{
    str = ""
    tgt = substr($2,beg[$1],end[$1]-beg[$1])
    if ( tgt !~ /[*]/ ) {
        bef = substr($2,1,beg[$1]-1)
        aft = substr($2,end[$1]+1)
        sub(/.*[*]/,"",bef)
        sub(/[*].*/,"",aft)
        str = bef tgt aft
    }
    print $1, beg[$1], end[$1], str
}

$ awk -f tst.awk file1 file2
ID1 1 18 abcdefghijklmnopq
ID2 5 12 cdefghijlmno
ID3 9 24

给出您的更新示例:

$ cat tst.awk
NR==FNR {
    map[$1] = $2
    next
}
{
    val = map[$1]
    beg = $2
    end = $3
    str = ""
    tgt = substr(val,beg,end-beg)
    if ( tgt !~ /[*]/ ) {
        bef = substr(val,1,beg-1)
        aft = substr(val,end+1)
        sub(/.*[*]/,"",bef)
        sub(/[*].*/,"",aft)
        str = bef tgt aft
    }
    print $1, beg, end, str
}

$ awk -f tst.awk file2 file1
ID1 1 18 abcdefghijklmnopq
ID2 5 12 cdefghijlmno
ID3 9 24
ID2 7 14 cdefghijklno