Удалите всю строку, начинающуюся со специального символа, за исключением первого слова

Я совсем недавно начал использовать linux, и я почти полностью забываю о командах sed. Мне нужно отредактировать файл, который содержит кучу длинных строк, начинающихся с общего символа «>», и удалять остальную часть этой строки, сохраняя только первое слово, но не касаясь строк, которые не начинаются с «>» с помощью команды sed.

Другими словами, мне нужно включить это (только часть первой записи для демонстрационных целей):

>YAL001C TFC3 SGDID:S000000001, Chr I from 151006-147594,151166-151097, Genome Release 64-1-1, reverse complement, Verified ORF, "Largest of six subunits of the RNA polymerase III transcription initiation factor complex (TFIIIC); part of the TauB domain of TFIIIC that binds DNA at the BoxB promoter sites of tRNA and similar genes; cooperates with Tfc6p in DNA binding" MVLTIYPDELVQIVSDKIASNKGKITLNQLWDISGKYFDLSDKKVKQFVLSCVILKKDIE VYCDGAIP* 

в это:

 >YAL001C MVLTIYPDELVQIVSDKIASNKGKITLNQLWDISGKYFDLSDKKVKQFVLSCVILKKDIE VYCDGAIP* 

Я представляю здесь четыре решения, два с использованием sed , один с использованием awk и один с использованием perl . Начать:

 $ sed -r 's/^(>[^ ]+) .*/\1/' inputfile 

На вашем примере ввода это приводит к выводу:

 >YAL001C LTIYPDELVQIVSDKIASNKGKITLNQLWDISGKYFDLSDKKVKQFVLSCVILKKDIE VYCDGAIP* 

Код использует команду замены sed s . Команда replace находится в форме s/old/new/ . В этом случае «старая» часть состоит из следующих частей:

  • ^

    Это sed-speak для начала строки.

  • (>[^ ]+)

    Это относится к группе символов, состоящей из угловой скобки, за которой следует один или несколько непустых символов. Поскольку это в скобках, мы сможем ссылаться на него позже как \1 .

  • .*

    Это означает пробел, за которым следует любое количество символов.

Когда команда substitute выполняется, вся любая такая строка заменяется только символами > и непустым символом, которые сразу же следуют за ним.

Любые строки, не начинающиеся с этой комбинации, отправляются на выход без изменений.

Альтернативное решение

В комментариях steeldriver предлагает альтернативный подход:

 sed '/^>/ s/\s.*//' 

В этом решении заменяющей команде предшествует модификатор /^>/ который ограничивает команду substitute для работы только с линиями, начинающимися с > . Зная, что линия начинается с угловой скобки, тогда нужно только удалить первый пробел и все, что следует за первым пробелом. Это то, что делает команда s/\s.*// .

Все остальные строки передаются без изменений.

Альтернативное решение с использованием awk

 awk '/^>/ {print $1;next} 1' inputfile 

Этот скрипт awk состоит из двух выражений:

  • /^>/ {print $1;next}

    awk поддерживает тот же стиль модификаторов, что и sed . Исходное выражение, таким образом, ограничивает эту команду действиями только для строк, начинающихся с > . Для этих строк печатается первое поле. next говорит awk чтобы перейти к следующей строке и начать все заново.

  • 1

    1 является критической короткой рукой awk для печати всей строки. Это выполняется только в строках, для которых next команда в предыдущем выражении не выполняется, что означает, что awk достигает этой команды, только если строка не начинается с > .

Альтернативное решение с использованием perl

steeldriver также предлагает:

 perl -anle 'print $F[0] if /^>/ || $_' 

Четыре варианта имеют следующее значение:

  • -n указывает perl на неявный цикл по входным строкам

  • -a сообщает perl включить автосплиту, создав @F

  • -l позволяет автоматическую обработку окончания строки

  • -e сообщает ему, чтобы он выполнял следующую команду, устраняя необходимость в файле сценария perl.

Сама команда perl достаточно читаема:

 print $F[0] if /^>/ || $_ 

Эта команда печатает первое поле, если строка начинается с > . В противном случае он печатает всю строку.