使用 bash 中的参考列表替换 newick 文件的提示

Replace tip of newick file using reference list in bash

我有一组包含基因 ID 的 newick 格式文件:

((gene1:1,gene2:1)100:1,gene3:1)100;
((gene4:1,gene5:1)100:1,gene6:1)100;

我有一个基因 ID 和物种名称之间的等价列表:

speciesA=(gene1,gene4)
speciesB=(gene2,gene5)
speciesC=(gene3,gene6)

我想获得以下输出:

((speciesA:1,speciesB:1)100:1,speciesC:1)100;
((speciesA:1,speciesB:1)100:1,speciesC:1)100;

知道我该如何继续吗?理想情况下 bash 会很棒 :)

input.txt

((gene1:1,gene2:1)100:1,gene3:1)100;
((gene4:1,gene5:1)100:1,gene6:1)100;

equivs.txt

speciesA=(gene1,gene4)
speciesB=(gene2,gene5)
speciesC=(gene3,gene6)

convert.sh

#!/bin/bash


function replace() {
    output=
    for line in $(cat equivs.txt)  #this will fail if there is whitespace in your lines!
    do
        #gets the replacement string
        rep=$(echo $line | cut -d'=' -f1)

        #create a regex of all the possible matches we want to replace with $rep 
        targets=$(echo $line | cut -d'(' -f2- | cut -d')' -f1) 
        regex="($(echo $targets | sed -r 's/,/|/g'))"

        #do the replacements   
        output=$(echo $output | sed -r "s/${regex}/${rep}/g")
    done
    echo $output
}

#step through the input, file calling the above function on each line.
#assuming all lines are formatted like the example!
for line in $(cat input.txt)
do
    replace $line
done

输出:

((speciesA:1,speciesB:1)100:1,speciesC:1)100;
((speciesA:1,speciesB:1)100:1,speciesC:1)100;

这是一个 awk 单行代码,可以满足您的需求:

$ awk -F'[()=,]+' 'NR==FNR{a[]=a[]=;next}{for(i in a)gsub(i,a[i])}1' species gene
((speciesA:1,speciesB:1)100:1,speciesC:1)100;
((speciesA:1,speciesB:1)100:1,speciesC:1)100;

浏览包含物种和基因之间映射的文件,将它们保存为数组 a 中的键值对。 NR==FNR 以传递给 awk 的第一个文件为目标,因为总行号 NR 等于当前文件中的行号 FNRnext 跳过任何进一步的说明。浏览第二个文件并进行替换。