我有一个带有标识符(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
说明:
字符串可以以星号开头和/或结尾,随后可以出现多个星号,并且字符串也可以完全没有星号。 file2中有一些ID在file1中没有。每个ID中File1可以包含多行,每个ID中file2仅包含一行。
希望我能明确我的问题。我对此还很陌生,感谢您的帮助。
答案 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