用名称标记树文件

  • 本文关键字:文件 shell awk
  • 更新时间 :
  • 英文 :


我有一个Newick/phillip格式的文件,如下所示

(Chicken:0.247775,
Mouse:0.091619,
(GuineaPig:0.174006,
((OwlMonkey:0.069823,
((Chimp:0.009091,
Human:0.009091):0.025108,
GreenMonkey:0.018831):0.015025):0.029561,
((Sheep:0.087386,
Pig:0.039886):0.022893,
Dog:0.068016):0.005950):0.023011):0.006297);

我需要将分支Dog标记为Dog:0.068016#Del

(Chicken:0.247775,
Mouse:0.091619,
(GuineaPig:0.174006,
((OwlMonkey:0.069823,
((Chimp:0.009091,
Human:0.009091):0.025108,
GreenMonkey:0.018831):0.015025):0.029561,
((Sheep:0.087386,
Pig:0.039886):0.022893,
Dog:0.068016#Del):0.005950):0.023011):0.006297);

这很容易用sed 's/Dog:0.068016/Dog:0.068016#Del/g'

完成但是我有多个具有不同值的文件,并且必须对其他动物进行多次更改,所以我尝试使用以下方法

sed '/'Dog'/s/Dog/#Del/'

但它没有工作。有什么建议吗?

使用单个调用GNU awk(用于gensub()和word boundaries)来一次更新尽可能多的目标:

$ cat tst.awk
BEGIN {
split(t,tmp)
for (i in tmp) {
tgts[tmp[i]]
}
}
{
for (tgt in tgts) {
$0 = gensub("\<(" tgt ":[0-9.]+)","\1#Del",1)
}
print
}

$ awk -v t='Dog' -f tst.awk file
(Chicken:0.247775,
Mouse:0.091619,
(GuineaPig:0.174006,
((OwlMonkey:0.069823,
((Chimp:0.009091,
Human:0.009091):0.025108,
GreenMonkey:0.018831):0.015025):0.029561,
((Sheep:0.087386,
Pig:0.039886):0.022893,
Dog:0.068016#Del):0.005950):0.023011):0.006297);

$ awk -v t='Dog Human Mouse' -f tst.awk file
(Chicken:0.247775,
Mouse:0.091619#Del,
(GuineaPig:0.174006,
((OwlMonkey:0.069823,
((Chimp:0.009091,
Human:0.009091#Del):0.025108,
GreenMonkey:0.018831):0.015025):0.029561,
((Sheep:0.087386,
Pig:0.039886):0.022893,
Dog:0.068016#Del):0.005950):0.023011):0.006297);

如果你要修改的数据在一个名为myFile的文件中,你的动物是简单的单词(只是字母),每行一个,在一个名为list的文件中,那么你可以在GNUsed的shell循环中做你想做的事情,就像你已经开始的那样:

cat list | while read animal; do
sed -E 's/<('"$animal"':[0-9.]*)/1#Del/' myFile > "$animal".out
done

对于列表中的每个animal,将创建一个名为animal.out的文件,其中包含修改后的数据。

GNUsed命令使用扩展正则表达式(-E)。

要搜索和替换的正则表达式(<('"$animal"':[0-9.]*))以单词开头(<)开始,使得动物名称在另一个名称中间的任何地方都不匹配。左括号开始记录匹配的子表达式;右括号结束录音。我们使用单引号和双引号来扩展shell变量animal(1)。然后我们找到一个冒号,后面跟着任意数量的数字或句点([0-9.]*)。

替换表达式使用第一个(也是唯一一个)记录的匹配子表达式(1)。

我们可以改进正则表达式中与动物名字后面的数字匹配的部分:[0-9]*.[0-9]*,以保证它只包含一个句点。如果你对这些数字有更多的了解,我们可以更具体地说:[0-9]+.[0-9]+,如果你总是在句点前后至少有一个数字。

(1)如果你的动物名字真的是简单的单词,$animal周围的双引号是无用的;但是,对这种类型的参数展开进行双引号引用是一种很好的做法,而且不会有什么坏处。

相关内容

  • 没有找到相关文章

最新更新