Это обеспечивает полное соответствие строки от =
до конца -gene=<number>
на каждой строке .gff3 и должно быть на несколько порядков быстрее и надежнее, чем то, что мы делали ранее, поскольку оно заменяет только 1 -3 строки, фактически найденные в каждой строке исходного файла .gff3, вместо попытки заменить все 18 000+ строк, которые существуют в файле rename.txt:
$ cat tst.awk
NR==FNR {
map[$1] = $2
next
}
{
head = ""
tail = $0
while ( match(tail,/((ID|Parent|Name)=)([^;]+-gene-[0-9]+\.[0-9]+)(.*)/,a) ) {
old = a[3]
head = head substr(tail,1,RSTART-1) a[1] (old in map ? map[old] : old)
tail = a[4]
}
print head tail
}
.
$ awk -f tst.awk rename.txt original.gff3
tulip_contig_65_pilon_pilon . contig 1 93354 . . . ID=tulip_contig_65_pilon_pilon;Name=tulip_contig_65_pilon_pilon
tulip_contig_65_pilon_pilon maker gene 19497 23038 . + . ID=gene3;Name=gene3
tulip_contig_65_pilon_pilon maker mRNA 19497 23038 . + . ID=gene3-mRNA-1;Parent=gene3;Name=gene3-mRNA-1;_AED=0.00;_eAED=0.00;_QI=418|1|1|1|0|0|3|2100|206
Он использует GNU awk для третьего аргумента для match () - я предполагаю, что у вас есть GNU awk (или вы можете его установить), так как вы использовали GNU sed.
Итак, match()
изолирует строку (который затем сохраняется в old
) из текущей строки original.gff3
, что может быть в rename.txt
(как хранится в map[]
в первом блоке), а затем old in map
проверка, действительно ли эта строка находится в rename.txt
или нет, и, если да, заменяет old
соответствующим новым значением из map[]
. Это все внутри while
, который зацикливается, пока match()
продолжает находить новые строки, которые являются кандидатами на замену в текущей строке.
Итак, вместо исходного сценария awk ниже (и сценария sed в вашем вопрос), который повторяется один раз для каждой из 18000+ строк в rename.txt
, приведенный выше цикл повторяется только один раз для каждой строки в текущей строке original.gff3
, которую, возможно, потребуется заменить, что, согласно вашему опубликованному образцу ввода, составляет только до 3 раз.
Исходный ответ, основанный на простом ускорении вашей оболочки l oop вызов sed:
Что-то вроде этого вам нужно:
$ cat tst.awk
NR==FNR {
map[$1] = $2
next
}
{
for (old in map) {
gsub(old,map[old])
}
print
}
.
$ awk -f tst.awk repl.txt foo.gff3
tulip_contig_65_pilon_pilon . contig 1 93354 . . . ID=tulip_contig_65_pilon_pilon;Name=tulip_contig_65_pilon_pilon
tulip_contig_65_pilon_pilon maker gene 19497 23038 . + . ID=gene3;Name=gene3
tulip_contig_65_pilon_pilon maker mRNA 19497 23038 . + . ID=gene3-mRNA-1;Parent=gene3;Name=gene3-mRNA-1;_AED=0.00;_eAED=0.00;_QI=418|1|1|1|0|0|3|2100|206
Существуют некоторые решения относительно сопоставления строк и регулярных выражений и полного и частичного сопоставления, которые также применяются к вашей оболочке + sed l oop, поэтому подумайте о своих полных требованиях и предоставьте образцы ввода / вывода для тестирования, а затем мы можем обработать это для подходит, если это не совсем то, что вам нужно. Прямо сейчас он выполняет частичное сопоставление регулярных выражений, как это делает команда sed в вашем вопросе.