Поиск конкретных слов и удаление всех строк после него

У меня есть файл, содержащий следующую информацию:

gene 3025..3855 /gene="Sp34_10000100" /ID="Sp34_10000100" CDS join(3025..3106,3722..3855) /gene="Sp34_10000100" /codon_start=1 /ID="Sp34_10000100.t1.cds1,Sp34_10000100.t1.cds2" mRNA 3025..3855 /ID="Sp34_10000100.t1" /gene="Sp34_10000100" gene 12640..13470 /gene="Sp34_10000200" /ID="Sp34_10000200" CDS join(12640..12721,13337..13470) /gene="Sp34_10000200" /codon_start=1 /ID="Sp34_10000200.t1.cds1,Sp34_10000200.t1.cds2" mRNA 12640..13470 /ID="Sp34_10000200.t1" /gene="Sp34_10000200" gene 15959..20678 /gene="Sp34_10000300" /ID="Sp34_10000300" CDS join(15959..16080,16268..16367,18913..19116,20469..20524,20582..20678) /gene="Sp34_10000300" /codon_start=1 /ID="Sp34_10000300.t1.cds1,Sp34_10000300.t1.cds2,Sp34_10000300.t1.cds3,Sp34_10000300.t1.cds4,Sp34_10000300.t1.cds5" mRNA 15959..20678 /ID="Sp34_10000300.t1" /gene="Sp34_10000300" gene 22255..23085 /gene="Sp34_10000400" /ID="Sp34_10000400" 

Я хочу удалить все секции генов, но информация о CDS и мРНК должна быть там. Результат должен выглядеть следующим образом:

 CDS join(3025..3106,3722..3855) /gene="Sp34_10000100" /codon_start=1 /ID="Sp34_10000100.t1.cds1,Sp34_10000100.t1.cds2" mRNA 3025..3855 /ID="Sp34_10000100.t1" /gene="Sp34_10000100" CDS join(12640..12721,13337..13470) /gene="Sp34_10000200" /codon_start=1 /ID="Sp34_10000200.t1.cds1,Sp34_10000200.t1.cds2" mRNA 12640..13470 /ID="Sp34_10000200.t1" /gene="Sp34_10000200" CDS join(15959..16080,16268..16367,18913..19116,20469..20524,20582..20678) /gene="Sp34_10000300" /codon_start=1 /ID="Sp34_10000300.t1.cds1,Sp34_10000300.t1.cds2,Sp34_10000300.t1.cds3,Sp34_10000300.t1.cds4,Sp34_10000300.t1.cds5" mRNA 15959..20678 /ID="Sp34_10000300.t1" /gene="Sp34_10000300" 

Пожалуйста, дайте мне какое-нибудь предложение, как это сделать.

awk обычно легче читать и понимать:

Вот простая программа, которая записывает по умолчанию и переключает «wewrite» на «0» (= off, мы не будем писать), когда видит линию, где первое слово является «геном», и возвращает его обратно, когда он видит линию, где первое слово – «CDS» или «mRNA»:

 awk ' BEGIN { weprint=1 } ( $1 == "gene" ) { weprint=0 } ( $1 == "CDS" ) || ( $1 == "mRNA" ) { weprint=1 } ( weprint == 1) { print $0 ;} ' file_to_read 

BEGIN выполняется до чтения любых строк.

Другой ( test ) { action if test successful } прошел синтаксический ( test ) { action if test successful } для каждой строки ввода (… если действие не содержит next , которое затем игнорирует остальные, а вместо этого будет извлекать следующую строку ввода)

Это будет печатать только разделы «CDS» и «mRNA», а не «ген»,

Это может быть «сыграно в гольф» (например, действие по умолчанию для успешного теста – это напечатать $ 0, так что вы могли бы иметь только ( weprint == 1) в качестве последней строки, но было бы менее понятно понять, imo …)

 sed -e ' /^ *gene /!b # print non-gene block begin lines :a $d; N # do-while loop accumulates lines for gene block s/\n *\///;ta D # clip the gene block ' yourfile 

Вам нужно понять, что sed модель – это чтение файла на основе строки, а команда sed в разделе -e применяется последовательно в строке, поскольку она преобразуется, если только не используются инструкции branching . И базовый синтаксис sed – это address command где команда может быть любой действительной командой sed а address может быть любой из них: linenum , $ (= last line), regex , range of addresses и, наконец, ничего не значит, что это применяется к ALL линиям , Обратите внимание, что строки хранятся в регистре, называемом pattern space .

Таким образом, с учетом этого основного материала, мы переходим к фактическому sed -e коду: b => отведите конец кода sed и напечатайте пространство шаблона. Это означает, что мы продолжаем печатать любую строку, которая НЕ (после шаблона адреса) имеет строковый gene поскольку это первое поле.

Когда мы, наконец, попадаем в gene в первой строке поля, мы настраиваем цикл do-while ( :a устанавливает метку, на которую нужно перепрыгнуть), чтобы сохранить накопление строк в регистре пространственного пространства ( N добавляет следующую команду; команда s удаляет \n *\/ , который является разрывом строки, за которым следуют пробелы и a) до тех пор, пока не будет выполнено одно из двух условий, а именно: либо мы удалим eof => мы удалим его ( $d => удалите пространство с образцом, если мы находимся в последней строке), так как это блок генов, который появился к eof и должен идти.

ИЛИ мы нажимаем начало следующего блока: если s может найти и удалить указанный шаблон, t будет переходить к :a , в противном случае (новый блок, поэтому шаблон не был найден), мы продолжаем. Теперь пространство шаблонов содержит весь блок гена и первую строку следующего блока. Мы незамедлительно удалим блок гена, и с началом следующего блока мы перейдем к началу sed-кода (это то, что делает команда D ).

Я не могу удержаться, чтобы дать ответ perl, когда мы ответили sed и awk !

 # make perl complain when it should use strict; use warnings; # declare variable my $section; # run through every line while (<>) { # set the current section to 'gene', 'CDS' or 'mRNA' when it matches $section = $1 if /^\h*(gene|CDS|mRNA)/; # print if the current section is not 'gene' print if $section ne 'gene'; }