Здесь мы должны сделать предположение, что строка версии (является строкой, а не числом )состоит из четырех полей, разделенных точкой. Итак, просто перехватите последний в LHS вашего регулярного выражения.
Я также рекомендую сначала сосредоточиться на строке, начинающейся с version=
, и касаться только части после символа =
. Поместите свое регулярное выражение в одинарные кавычки, чтобы escape-последовательности \
не были упреждающе экранированы оболочкой. Кроме того, вам не нужно использовать (
и )
вокруг вашего совпадения, потому что вы не сохраняете его на потом.
sed -i -r '/version=/s/=.*\.[0-9][0-9]*$/version=11.21.2/g' <filename>
В приведенном выше примере я разрешаю последнему полю состоять из нескольких числовых символов. Возможно, вы захотите поместить туда произвольные символы, и в этом случае:
sed -r '/version=/s/=.*\.([^.]*)$/=11.21.2.\1/g' <filename>
Чтобы принять произвольное изменение в качестве входных данных, скажем:
newver=11.21.2
sed -r '/version=/s/=.*\.([^.]*)$/='${newver}'.\1/g' <filename>
Одним из способов достижения того, что вы описываете, является:
При использовании awk это будет, например,:
awk -F@ 'NR == FNR { if ($0 ~ /^>/) { a[$1] = $0 }; next } { if ($0 ~ /^>/ && $0 in a) $0 = a[$0]; print }' second_file_with_headers first_file
Пример:
$ cat second_file_with_headers
>TRINITY_DN100_c0_g1_i1 len=242 path=[0:0-241]@Guinardia_delicatula
AGCAATCCAAACTGCTGCAATCTGGGCTCGTGAAAACGATATGGTATTACACTTACACCGTGC
>TRINITY_DN100_c0_g1_i1 KR048205>TRINITY_DN105_c0_g1_i1 len=260 path=[0:0-259]AGCAATTCAAAGTGCTGCAATCTGGGCTCGTGAAAACGATATGTTATTACACTTACACCGTGCA
>TRINITY_DN103_c0_g1_i1 len=260 path=[0:0-259]@Luticola_sparsipunctata
AGCAATTCAAAGTGCTGCAATCTGGGCTCGTGAAAACGATATGATTTTACACTTACACCGTGCA
$ cat first_file
>TRINITY_DN100_c0_g1_i1 len=242 path=[0:0-241]
AGCAATTCAAACTGCTGCAATCTGGGCTCGTGAAAACGATATGGTATTACACTTACATCGTGCAAGACAAACAACAAGTGCGTTACGTCACGTTACGTTAATTCGTTCGTTCGTCTCTCTATTGCGTTGCGTTACGCTCTCGCCGCGGACCCAGCACCGCATACCCGCCCATACAAGTCATACAGTACACAACACAAAAACACAACCAACTATTTCCTTGGAAGAGAAAGCAAGCCCAAAAC
>TRINITY_DN105_c0_g1_i1 len=260 path=[0:0-259]
TGAAAATATTAATTCTCAACCTTTTATGCGTTGGAGAGAAAGATATTTATTTTCAATAGAGGGAGTTAATCGTGCAGCGGCAGCAAGTGGTGAAATTAAAGGACATTATTTAAATGTTACTGCAGGTACAATGGAAGACATGTACGAACGCGCCAAGATTGATGTGCCTGAGAACCACATGAATAACGAGGAGCAATACACACTTCACTACCAAGAGTACCTTGTGGGTAGCTCGGCTGGTGTGCCCAAGGATATGAAGG
>TRINITY_DN103_c0_g1_i1 len=260 path=[0:0-259]
GTTCTCTTCGGTGGCAGCCTTACGGCCGACCACCTGGTATTGTCGCATAATTCCCGCAGCAGTCATGATGTCTATTGTTTGTCGTGAAAAGAAATGAATTAAGAGAGTCATAGTTACTCCCGCCGTTTACCCGCGCTTGGTTGAATTCCTTCACTTTGACATTCAGAGCACTGGGCAGAAATCACATTGCGTCAACACCATCTCTGTTTCAACGAAATCAGCAGTATCTGTAGAAGTGTAGTTAAAACTAATATCTTTCC
$ awk -F@ 'NR == FNR { if ($0 ~ /^>/) { a[$1] = $0 }; next } { if ($0 ~ /^>/ && $0 in a) $0 = a[$0]; print }' second_file_with_headers first_file
>TRINITY_DN100_c0_g1_i1 len=242 path=[0:0-241]@Guinardia_delicatula
AGCAATTCAAACTGCTGCAATCTGGGCTCGTGAAAACGATATGGTATTACACTTACATCGTGCAAGACAAACAACAAGTGCGTTACGTCACGTTACGTTAATTCGTTCGTTCGTCTCTCTATTGCGTTGCGTTACGCTCTCGCCGCGGACCCAGCACCGCATACCCGCCCATACAAGTCATACAGTACACAACACAAAAACACAACCAACTATTTCCTTGGAAGAGAAAGCAAGCCCAAAAC
>TRINITY_DN105_c0_g1_i1 len=260 path=[0:0-259]
TGAAAATATTAATTCTCAACCTTTTATGCGTTGGAGAGAAAGATATTTATTTTCAATAGAGGGAGTTAATCGTGCAGCGGCAGCAAGTGGTGAAATTAAAGGACATTATTTAAATGTTACTGCAGGTACAATGGAAGACATGTACGAACGCGCCAAGATTGATGTGCCTGAGAACCACATGAATAACGAGGAGCAATACACACTTCACTACCAAGAGTACCTTGTGGGTAGCTCGGCTGGTGTGCCCAAGGATATGAAGG
>TRINITY_DN103_c0_g1_i1 len=260 path=[0:0-259]@Luticola_sparsipunctata
GTTCTCTTCGGTGGCAGCCTTACGGCCGACCACCTGGTATTGTCGCATAATTCCCGCAGCAGTCATGATGTCTATTGTTTGTCGTGAAAAGAAATGAATTAAGAGAGTCATAGTTACTCCCGCCGTTTACCCGCGCTTGGTTGAATTCCTTCACTTTGACATTCAGAGCACTGGGCAGAAATCACATTGCGTCAACACCATCTCTGTTTCAACGAAATCAGCAGTATCTGTAGAAGTGTAGTTAAAACTAATATCTTTCC
$
Сценарий awk можно довольно легко объяснить:
awk # the awk program, can be gawk, mawk or any other implementation
-F@ # Sets FS="@". This tells awk to split on the @ character.
NR == FNR { if ($0 ~ /^>/) { a[$1] = $0 }; next }
# While handling the first argument (here, second_file_with_headers)
# For lines starting with >, store the line into an array with the part before @ as the key
# Discard all lines in this file with 'next'
{ if ($0 ~ /^>/ && $0 in a) $0 = a[$0]; print }
# For all other lines, meaning that we are now working on the second argument (first_file)
# For lines starting with >, change the line into the stored version from the array if it exists
# then print the line
second_file_with_headers
# Use the file with the headers as the first argument
first_file
# Use the file which needs to be updated as the second argument
awk -F'[@[:blank:]]+' '
NR==FNR { if(/^>/) seen[$1]=$NF; next }
{ if($1 in seen) $0=$0 "@" seen[$1]; print }' second.fasta first.fasta
с -F
мы можем указать F разделитель полей, который мы установили на @
символ, а также пробелы([:blank:]
Tabs/Spaces ), где они могут встречаться один -или -еще раз [...]+
; поэтому поля будут разделены этими символами.
NF==FNR
всегда истинное условие в awk которое истинно для первого входного файла всегда(second.fasta файл здесь ); NR
и FNR
увеличиваются для каждой строки ввода, но FNR
сбрасывается обратно на 1 для следующего входного файла.
это if(/^>/)
условие, которое проверяет, начинается ли строка(^
в регулярном выражении до начала строки )с символом >
, если да, то держим последнее поле $NF
в связанный массив (мы назовем егоseen
)и поле #1 $1
будем использовать в качестве ключей.
оператор next
пропускает обработку остальных кодов и снова переходит к началу кода; если условие NR==FNR
все еще было истинным, он будет повторять следующий код NR==FNR {... }
, иначе будет выполнен следующий блок, который выполняется во втором входном файле first.fasta , который мы проверяем, если первое поле в его можно найти в массиве seen
или нет, если да, то добавить в конец этой строки значение найденного ключа и затем сделать print
все, что есть во всей строке$0
(либо обновлено, либо нет ).
Или, если все заголовки в обоих файлах представлены, а также находятся в одном и том же номере строки, вы можете сделать следующее вместо буферизации файла second.fasta в память:
paste -d@ first.fasta second.fasta |awk -F@ '/^>/{ $1=$1 $NF } { print $1 }'