我有gff
文件,内容如下(制表符分隔):
# start gene 1Chr.g1
1Chr AUGUSTUS gene 3636 5916 0.1 + . ID=1Chr.g1
1Chr AUGUSTUS transcript 3636 5916 0.1 + . ID=1Chr.g1.t1;Parent=1Chr.g1
1Chr AUGUSTUS transcription_start_site 3636 3636 . + . Parent=1Chr.g1.t1
1Chr AUGUSTUS exon 3636 3913 . + . Parent=1Chr.g1.t1
1Chr AUGUSTUS start_codon 3760 3762 . + 0 Parent=1Chr.g1.t1
1Chr AUGUSTUS intron 3914 3995 1 + .
1Chr AUGUSTUS CDS 3760 3913 1 + 0 ID=1Chr.g1.t1.cds;Parent=1Chr.g1.t1
1Chr AUGUSTUS stop_codon 5628 5630 . + 0 Parent=1Chr.g1.t1
1Chr AUGUSTUS transcription_end_site 5916 5916 . + . Parent=1Chr.g1.t1
# start gene 1Chr.g2
1Chr AUGUSTUS gene 5938 8761 0.17 - . ID=1Chr.g2
1Chr AUGUSTUS transcript 5938 8761 0.17 - . ID=1Chr.g2.t1;Parent=1Chr.g2
1Chr AUGUSTUS transcription_end_site 5938 5938 . - . Parent=1Chr.g2.t1
1Chr AUGUSTUS exon 5938 6594 . - . Parent=1Chr.g2.t1
1Chr AUGUSTUS stop_codon 6428 6430 . - 0 Parent=1Chr.g2.t1
1Chr AUGUSTUS intron 6595 7156 0.8 - . Parent=1Chr.g2.t1
1Chr AUGUSTUS CDS 6428 6594 0.89 - 2 ID=1Chr.g2.t1.cds;Parent=1Chr.g2.t1
# start gene 2Chr.g1
2Chr AUGUSTUS gene 11612 13481 0.09 - . ID=2Chr.g1
2Chr AUGUSTUS transcript 11612 13481 0.09 - . ID=2Chr.g1.t1;Parent=2Chr.g1
2Chr AUGUSTUS transcription_end_site 11612 11612 . - . Parent=2Chr.g1.t1
2Chr AUGUSTUS exon 11612 13481 . - . Parent=2Chr.g1.t1
2Chr AUGUSTUS stop_codon 11864 11866 . - 0 Parent=2Chr.g1.t1
2Chr AUGUSTUS CDS 11864 12940 1 - 0 ID=2Chr.g1.t1.cds;Parent=2Chr.g1.t1
2Chr AUGUSTUS start_codon 12938 12940 . - 0 Parent=2Chr.g1.t1
2Chr AUGUSTUS transcription_start_site 13481 13481 . - . Parent=2Chr.g1.t1
# start gene 2Chr.g2
2Chr AUGUSTUS gene 22876 31223 0.04 + . ID=2Chr.g2
2Chr AUGUSTUS transcript 22876 31223 0.04 + . ID=2Chr.g2.t1;Parent=2Chr.g2
2Chr AUGUSTUS transcription_start_site 22876 22876 . + . Parent=2Chr.g2.t1
2Chr AUGUSTUS exon 22876 23456 . + . Parent=2Chr.g2.t1
2Chr AUGUSTUS exon 23515 24451 . + . Parent=2Chr.g2.t1
2Chr AUGUSTUS start_codon 23519 23521 . + 0 Parent=2Chr.g2.t1
我想替换1Chr.g1
,1Chr.g2
,2Chr.g1
和2Chr.g2
基因的id,就像从g1
开始到id结束的顺序,就像在这种情况下的g4
。
预期输出
# start gene g1
1Chr AUGUSTUS gene 3636 5916 0.1 + . ID=g1
1Chr AUGUSTUS transcript 3636 5916 0.1 + . ID=g1.t1;Parent=g1
1Chr AUGUSTUS transcription_start_site 3636 3636 . + . Parent=g1.t1
1Chr AUGUSTUS exon 3636 3913 . + . Parent=g1.t1
1Chr AUGUSTUS start_codon 3760 3762 . + 0 Parent=g1.t1
1Chr AUGUSTUS intron 3914 3995 1 + .
1Chr AUGUSTUS CDS 3760 3913 1 + 0 ID=g1.t1.cds;Parent=g1.t1
1Chr AUGUSTUS stop_codon 5628 5630 . + 0 Parent=g1.t1
1Chr AUGUSTUS transcription_end_site 5916 5916 . + . Parent=g1.t1
# start gene g2
1Chr AUGUSTUS gene 5938 8761 0.17 - . ID=g2
1Chr AUGUSTUS transcript 5938 8761 0.17 - . ID=g2.t1;Parent=g2
1Chr AUGUSTUS transcription_end_site 5938 5938 . - . Parent=g2.t1
1Chr AUGUSTUS exon 5938 6594 . - . Parent=g2.t1
1Chr AUGUSTUS stop_codon 6428 6430 . - 0 Parent=g2.t1
1Chr AUGUSTUS intron 6595 7156 0.8 - . Parent=g2.t1
1Chr AUGUSTUS CDS 6428 6594 0.89 - 2 ID=g2.t1.cds;Parent=g2.t1
# start gene g3
2Chr AUGUSTUS gene 11612 13481 0.09 - . ID=g3
2Chr AUGUSTUS transcript 11612 13481 0.09 - . ID=g3.t1;Parent=g3
2Chr AUGUSTUS transcription_end_site 11612 11612 . - . Parent=g3.t1
2Chr AUGUSTUS exon 11612 13481 . - . Parent=g3.t1
2Chr AUGUSTUS stop_codon 11864 11866 . - 0 Parent=g3.t1
2Chr AUGUSTUS CDS 11864 12940 1 - 0 ID=g3.t1.cds;Parent=g3.t1
2Chr AUGUSTUS start_codon 12938 12940 . - 0 Parent=g3.t1
2Chr AUGUSTUS transcription_start_site 13481 13481 . - . Parent=g3.t1
# start gene g4
2Chr AUGUSTUS gene 22876 31223 0.04 + . ID=g4
2Chr AUGUSTUS transcript 22876 31223 0.04 + . ID=g4.t1;Parent=g4
2Chr AUGUSTUS transcription_start_site 22876 22876 . + . Parent=g4.t1
2Chr AUGUSTUS exon 22876 23456 . + . Parent=g4.t1
2Chr AUGUSTUS exon 23515 24451 . + . Parent=g4.t1
2Chr AUGUSTUS start_codon 23519 23521 . + 0 Parent=g4.t1
我写了下面的bash脚本,但是它花了太长时间,因为我试图计算它的时间,所以对于一个sed
它花了1秒,如果有28000
迭代,它将花费大约8小时,这是太多的时间。有什么有效的方法吗?
awk '$3 == "gene"' $1 |cut -f9 |grep -o "=.*" |sed -e 's/=//g' >LIST.txt
COUNTER=0
cat LIST.txt | while read line; do
COUNTER=$(expr $COUNTER + 1)
echo "sed -i 's/$line/g$COUNTER/g' $1" |bash
done
rm LIST.txt
另一件事,生成一个文件sedTG45
,这是非常烦人的。
您在同一个文件上运行sed
多达28,000次。只要稍加预处理,就不难把它压缩到一次。
这是未经测试的,但至少应该为您指明Awk的大致方向。这是一种很小的语言;你可以在不到一个小时的时间里学会它,并在几个星期内变得相当熟练。
awk -F 't' '$3 == "gene" {
g=$9; sub(/^[^=]*=/, "", g); gsub(/=/, "", g);
a[g] = "g" ++n }
{ for(k in a) gsub(k, a[k]) }1' "$1"
简而言之,n
维持计数器,a
是我们取出的所有基因的关联数组。
这假设定义在应该被替换的出现之前。如果这不是一个有效的假设,您将需要对文件进行两次迭代,但第一次将是只读的,因此这仍然应该比您的暴力尝试要快得多。
附录:如果您执意要坚持使用(已更新的)代码,那么在done
之后将管道移到Bash(或者仅仅是sed
)将会显著改进它。这是一个简单的重构。用Awk还是会更漂亮。
# Use lower case for private variable
counter=0
# Note quotes around $1
# and use of pipe instead of temp file
awk '$3 == "gene"' "$1" |
cut -f9 |
grep -o "=.*" |
sed -e 's/=//g' |
# note IFS='' and read -r
while IFS='' read -r line; do
# avoid paleolithic expr
((counter++))
echo "s/$line/g$COUNTER/g"
done |
# pipe output to sed -i
sed -i -f - "$1"
不是所有的sed
s都允许-f -
。当sed -i
运行时,不可避免地会有一个临时文件,但它会在完成后被删除。
演示,带时序:https://ideone.com/GghqiW
首先生成sed
命令可能会有所帮助。输入文件将被读取两次,但这应该不是问题。请检查演出。
你想要的sed
命令看起来像
s/1Chr.g1.t1/g1/g
s/1Chr.g2.t1/g2/g
s/2Chr.g1.t1/g3/g
s/2Chr.g2.t1/g4/g
当数字大于9时,这些命令可能是错误的,所以稍微改变一下:
awk '
($0 != last) {
n++;
printf("s/([^0-9])%s([^0-9]|$)/\1g%s\2/gn", $0, n)
}
{
last=$0
}' <(grep -Eo "[0-9]+Chr.g[0-9]+" < file)
返回s/([^0-9])1Chr.g1([^0-9]|$)/1g12/g
s/([^0-9])1Chr.g2([^0-9]|$)/1g22/g
s/([^0-9])2Chr.g1([^0-9]|$)/1g32/g
s/([^0-9])2Chr.g2([^0-9]|$)/1g42/g
现在在sed
中使用这些命令(将文件替换为$1
在2个地方,将-i
添加到sed
,当它看起来ok时):
sed -r -f <(
awk '
($0 != last) {
n++;
printf("s/([^0-9])%s([^0-9]|$)/\1g%s\2/gn", $0, n)
}
{
last=$0
}' <(grep -Eo "[0-9]+Chr.g[0-9]+" < file)
) file
sed 's/([= ])[0-9]+Chr.(g[0-9]+)/12/g' file.gff
如果你敢做sed -i
,
我建议你先做一个副本。
还注意:将只与基于数字的染色体工作所以没有X,Y, mt,I,II,III, IV…等。