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

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

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

8 ответов

Предполагая много согласованности, вы можете использовать что-то вроде ...

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

Примечания

-r использовать ERE s/old/new заменить old на new (some chars) помнить, что some chars ссылается позже на \1 и т. д. [^ ]+ как минимум на один непространственный символ ([^_]+ - это хотя бы один символ без подчеркивания) \| literal |, поскольку в ERE | ] используется для чередования .* любое количество любых символов \1\2 назад ссылки на сохраненные паттерны
2
ответ дан 22 May 2018 в 19:03

Предполагая много согласованности, вы можете использовать что-то вроде ...

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

Примечания

-r использовать ERE s/old/new заменить old на new (some chars) помнить, что some chars ссылается позже на \1 и т. д. [^ ]+ как минимум на один непространственный символ ([^_]+ - это хотя бы один символ без подчеркивания) \| literal |, поскольку в ERE | ] используется для чередования .* любое количество любых символов \1\2 назад ссылки на сохраненные паттерны
2
ответ дан 18 July 2018 в 07:55
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 в конец команды, чтобы сохранить вывод в файле [ f5].

Объяснение

\(.*_\) берет все до первого подчеркивания, сохраняет его как группу 1 .*=, беря все, пока первый знак равенства не заменит .*OS= на возьмите все до тех пор, пока OS= \([A-Z][a-z ]*\) не возьмут одну букву верхнего регистра и все следующие строчные буквы и пробелы, сохраните ее как группу 2, замените на \([^ ]*[ ][^ ]*\), чтобы найти строку с ровно одним пробелом в ней .* (предшествующий пространство здесь не отображается!) возьмем пробел и остальную часть строки \1\2 group 1, за которой следует группа 2
3
ответ дан 22 May 2018 в 19:03
  • 1
    Спасибо за это, но, как я сделал вывод был & Гт зр | O34439 | YFLP_yflP MKKSIILLNILLIFMQGDIRQAAAPRLPDGPIEIVVPAEPSGGWDVTAQAIQSVLRQKQIVKDDVHIVYKSGGGGEKGWKYVNKSSKQTISMTSSLILSNDLLGQSKLKMSDFTPLAILSKEWQTVALPKGSALTNGKDVLNEINMHPGKVRIGFAPGFGNDDQLSFVRAADMYGIDPFDIQFSQYDSSEQLIQALIRHEIEAASMTLSEAKPYERNGDITLAAVTSDKRLPGFPNVPTWKEQGIPFVFSHWRGILGPKNMSEEEISYWDQALKKVTSSPEWKRKINEQDWESFYLNSRETKRFLEEQSAFYQSIMTGN & Гт зр | Q44018 | YGB7_Cupriavidus Necator MQRRHFIARAGIAAATAALGLAAMPAQAQADKFPQRPIRLVIGYTAGGSTDIPFRVLADNASKILGQPVIVENKPGAGGVLPAQMMQSTAPDGYTLAQVAMPVYRLPYTTKINWDPVKDLNYIINLAGYSFGLVVPADSPIKTMQEYIAYAKANPGKLTYGSPGSM – Leonardo T Rosa 28 August 2017 в 12:37
  • 2
    @LeonardoTRosa я исправил его, у первого был опечаток. Простите за это. – dessert 28 August 2017 в 13:08

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

$ 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
ответ дан 22 May 2018 в 19:03
  • 1
    @Занна *?= необходима для возврата групп 2 и 3, а первая может быть опущена – George Udosen 26 August 2017 в 17:07
  • 2
    @ Zanna Я согласен с *, но лучше проверил его здесь , чтобы понять, что я имею в виду – George Udosen 26 August 2017 в 17:22
  • 3
    О, я вижу, это ленивый или не жадный (в regex в стиле perl я думаю) ... Но признает ли sed это обозначение? Я не думаю, что это хмм. Кстати, ваш окончательный g также лишний, так как мы не сопоставляем шаблон более одного раза. – Zanna 26 August 2017 в 17:51
  • 4
    @ Zanna ok Я пока не вижу эксперта. Но обновленный ответ, спасибо. – George Udosen 26 August 2017 в 18:25
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 group 1, за которой следует группа 2
3
ответ дан 18 July 2018 в 07:55

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

$ 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
ответ дан 18 July 2018 в 07:55
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 group 1, за которой следует группа 2
3
ответ дан 24 July 2018 в 18:55
  • 1
    Спасибо за это, но, как я сделал вывод был & Гт зр | O34439 | YFLP_yflP MKKSIILLNILLIFMQGDIRQAAAPRLPDGPIEIVVPAEPSGGWDVTAQAIQSVLRQKQIVKDDVHIVYKSGGGGEKGWKYVNKSSKQTISMTSSLILSNDLLGQSKLKMSDFTPLAILSKEWQTVALPKGSALTNGKDVLNEINMHPGKVRIGFAPGFGNDDQLSFVRAADMYGIDPFDIQFSQYDSSEQLIQALIRHEIEAASMTLSEAKPYERNGDITLAAVTSDKRLPGFPNVPTWKEQGIPFVFSHWRGILGPKNMSEEEISYWDQALKKVTSSPEWKRKINEQDWESFYLNSRETKRFLEEQSAFYQSIMTGN & Гт зр | Q44018 | YGB7_Cupriavidus Necator MQRRHFIARAGIAAATAALGLAAMPAQAQADKFPQRPIRLVIGYTAGGSTDIPFRVLADNASKILGQPVIVENKPGAGGVLPAQMMQSTAPDGYTLAQVAMPVYRLPYTTKINWDPVKDLNYIINLAGYSFGLVVPADSPIKTMQEYIAYAKANPGKLTYGSPGSM – Leonardo T Rosa 28 August 2017 в 12:37

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

$ 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
ответ дан 24 July 2018 в 18:55
  • 1
    @Занна *?= необходима для возврата групп 2 и 3, а первая может быть опущена – George Udosen 26 August 2017 в 17:07
  • 2
    @ Zanna Я согласен с *, но лучше проверил его здесь , чтобы понять, что я имею в виду – George Udosen 26 August 2017 в 17:22
  • 3
    О, я вижу, это ленивый или не жадный (в regex в стиле perl я думаю) ... Но признает ли sed это обозначение? Я не думаю, что это хмм. Кстати, ваш окончательный g также лишний, так как мы не сопоставляем шаблон более одного раза. – Zanna 26 August 2017 в 17:51

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

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