Как исключить текст между двумя шаблонами в той же строке

У меня есть файл с входом

sp|O34439|YFLP_BACSU UPF0065 protein YflP OS=Bacillus subtilis (strain 168) GN=yflP PE=3 SV=2
MKKSIILLNILLIFMQGDIRQAAAPRLPDGPIEIVVPAEPSGGWDVTAQAIQSVLRQKQIVKDDVHIVYKSGGGGEK
sp|Q44018|YGB7_CUPNE UPF0065 protein in gbd 5'region OS=Cupriavidus necator PE=3 SV=1
MQRRHFIARAGIAAATAALGLAAMPAQAQADKFPQRPIRLVIGYTAGGSTDIPFRVLADNASKILGQPVIVENK

и потребность получить этот вывод:

sp|O34439|YFLP_Bacillus subtilis
MKKSIILLNILLIFMQGDIRQAAAPRLPDGPIEIVVPAEPSGGWDVTAQAIQSVLRQKQIVKDDVHIVYKSGGGGEK
sp|Q44018|YGB7_Cupriavidus necator
MQRRHFIARAGIAAATAALGLAAMPAQAQADKFPQRPIRLVIGYTAGGSTDIPFRVLADNASKILGQPVIVENK

Так, я должен исключить все между шаблоном >|......|.... и OS=.................... (Если я могу исключить OS= и отпуск , еще лучше), и исключают что-либо после второго шаблона в той же строке.

2
задан 28 August 2017 в 12:54

3 ответа

Принимая большую непротиворечивость, Вы могли использовать что-то как...

$ sed -r 's/([^ ]+\|[^ ]+\|[^_]+_)[^_]+ .* OS=([^ ]+ [^ ]+) .*/\1\2/' file
sp|O34439|YFLP_Bacillus subtilis
MKKSIILLNILLIFMQGDIRQAAAPRLPDGPIEIVVPAEPSGGWDVTAQAIQSVLRQKQIVKDDVHIVYKSGGGGEK
sp|Q44018|YGB7_Cupriavidus necator
MQRRHFIARAGIAAATAALGLAAMPAQAQADKFPQRPIRLVIGYTAGGSTDIPFRVLADNASKILGQPVIVENK

Примечания

  • -r использование ДО
  • s/old/new замена old с new
  • (some chars) помнит some chars для ссылки позже с \1 и т.д.
  • [^ ]+ по крайней мере один непробел ([^_]+, по крайней мере один несимвол подчеркивания)
  • \|, литерал | с тех пор в ДО | используется для чередования
  • .* любое количество любых символов
  • \1\2 обратные ссылки на сохраненные шаблоны
2
ответ дан 2 December 2019 в 01:43

Это будет работать:

$ sed -r 's/(.*_)[A-Z].*=(\w+)\s{1,2}(\w+)\s{1,2}.*\s.*/\1\2 \3/g' file.txt
sp|O34439|YFLP_Bacillus subtilis    
MKKSIILLNILLIFMQGDIRQAAAPRLPDGPIEIVVPAEPSGGWDVTAQAIQSVLRQKQIVKDDVHIVYKSGGGGEK
sp|Q44018|YGB7_Cupriavidus necator
MQRRHFIARAGIAAATAALGLAAMPAQAQADKFPQRPIRLVIGYTAGGSTDIPFRVLADNASKILGQPVIVENK

Объяснение:

  • (.*_) - вернуть все до первой буквы в верхнем регистре
  • .*= - взять до знака равенства
  • (\w+)\s{1,2} - вернуть первое слово перед 1-2 пробелами
  • (\w+)\s{1,2} - то же, что и выше
  • .*\s.* - получить все до пробела и все после этого
  • \1\2 \3 - возврат захваченных групп
1
ответ дан 2 December 2019 в 01:43
sed 's/\([^_]*\).*=\([A-Z][a-z ]*\).*/\1_\2/' test

делает то, что Вы хотите для файла test и пишет вывод в терминал:

> sed 's/\([^_]*\).*=\([A-Z][a-z ]*\).*/\1_\2/' test
sp|O34439|YFLP_Bacillus subtilis 
MKKSIILLNILLIFMQGDIRQAAAPRLPDGPIEIVVPAEPSGGWDVTAQAIQSVLRQKQIVKDDVHIVYKSGGGGEK
sp|Q44018|YGB7_Cupriavidus necator 
MQRRHFIARAGIAAATAALGLAAMPAQAQADKFPQRPIRLVIGYTAGGSTDIPFRVLADNASKILGQPVIVENK

Добавить > filename в конец команды для сохранения вывода в файле filename вместо этого.

Объяснение

  • \(.*_\) возьмите все до первого подчеркивания, сохраните его как группу 1
  • .*= возьмите все до первого знака "равно"
    • замена .*OS= взять все до OS=
  • \([A-Z][a-z ]*\) возьмите одну прописную букву и все следующие строчные буквы и пробелы, сохраните ее как группу 2
    • замена \([^ ]*[ ][^ ]*\) искать строку точно с одним пространством в нем
  • .* (предшествующий пространству, не отображенному здесь!) занимают место и остальную часть строки
  • \1\2 группа 1 сопровождается группой 2
3
ответ дан 2 December 2019 в 01:43

Другие вопросы по тегам:

Похожие вопросы: