Как получить все строки между частичными совпадениями с помощью awk или sed?

#awk #sed

Вопрос:

Мой файл выглядит примерно так:

 >Cluster 0
0   58aa, >5XX8A... at 91.38%
1   58aa, >3LDMA... at 100.00%
2   58aa, >3BTHI... at 96.55%
3   65aa, >1F7ZI... *
4   58aa, >3LDJA... at 100.00%
>Cluster 1
0   57aa, >1ZJDB... at 94.74%
1   58aa, >1AAPA... at 91.38%
2   56aa, >5NX1D... at 92.86%
>Cluster 2
0   60aa, >4ISLB... at 98.33%
1   62aa, >4ISNB... at 95.16%
>Cluster 3
0   59aa, >3BYBA... *
1   59aa, >5ZJ3A... at 100.00%
2   59aa, >3UIRC... at 100.00%
3   57aa, >3D65I... at 100.00%
 

Как я могу использовать sed или awk для получения идентификаторов после > (например: 5XX8A) между «>>Кластерами».
Я хочу иметь возможность сохранять их отдельно (в разных файлах). По одному файлу на кластер. Или что-то более поддающееся анализу, например, один файл с идентификаторами рядом с номером кластера.

В качестве первого подхода делаем что-то вроде:

 sed -n '/^>/,/^>/p' filename 
 

возвращает весь файл целиком :/

Комментарии:

1. Что вы подразумеваете под «получить», у вас есть желаемый формат? В настоящее время они сгруппированы с заголовком, указывающим на кластер. Так что, похоже, они в правильном формате.

2. Да, вы правы. Возможно, я был слишком общим. Я отредактировал его именно так, как мне нужно.

3. Вам нужно простое решение для bash без sed/awk ?

4. Да, это тоже работает!

Ответ №1:

awk на помощь!

 $ awk '/^>Cluster /{close(f); f="Cluster."$2; next} {sub(/>/,"",$3); print $3 > f}' file
  
$ head Cluster*
==> Cluster.0 <==
5XX8A...
3LDMA...
3BTHI...
1F7ZI...
3LDJA...

==> Cluster.1 <==
1ZJDB...
1AAPA...
5NX1D...

==> Cluster.2 <==
4ISLB...
4ISNB...

==> Cluster.3 <==
3BYBA...
5ZJ3A...
3UIRC...
3D65I...
 

Комментарии:

1. Это прекрасно! Спасибо 🙂 всего один вопрос. Для чего нам нужен «следующий»? Что он делает?

2. если вы удалите next его, он также напечатает заголовок в файле. Таким образом, он пропустит остальную часть сценария и перейдет к следующей строке.

Ответ №2:

Это может сработать для вас (GNU sed):

 sed -En '/^>(Cluster) /{s//>1./;:a;x;s/n(.*)/ echo "1"/e;x;h;d};s/.*>//;s/ .*//;H;$!d;ba' file
 

Соберите каждый кластер в пространстве хранения и, используя флаг оценки в команде подстановки, передайте коллекцию в имя файла, указанное в первой строке коллекции.

Альтернативный метод, использующий sed и трубопровод для транспортировки:

 sed '/^>Cluster/{s/ /./;h;d};s/..*>//;s/ .*//;G;x;s/>*/>>/;x;s/n/ /;s/S*/echo "amp;"/' file|sh
 

Альтернативный метод, использующий sed и csplit:

 sed 's/^..*>//;s/ .*//' file | csplit -szf Cluster -b '.%d' --suppress-matched - '/>Cluster/' '{*}'
 

Преобразуйте файл в нужный формат с помощью sed, а затем разделите файл на отдельные файлы с помощью csplit.

N. B. Это может не полностью воспроизвести имена файлов.