Мое (запутанное )предложение:
cat file | grep -Po "^[CGTA-]*$|^>.*$" | grep -Po "(?<=\[).*(?=])|^[ACGT-]*$" | awk '{printf (NR%2==0) ? $0 "\n" : ">"$0"::"}' | sort | sed 's/#/\n/'
Grep только строки, содержащие символы CGTA-
и строки, начинающиеся с>
grep -Po "^[CGTA-]*$|^>.*$"
Grep только то, что находится внутри скобок, исключая их и строки, соответствующие шаблонуACGT-
| grep -Po "(?<=\[).*(?=])|^[ACGT-]*$"
Соедините каждые две строки, добавив разделитель #
и начальную >
, затем отсортируйте
| awk '{printf (NR%2==0) ? $0 "\n" : ">"$0"#"}' | sort
Наконец, замените разделитель #
новой строкой
| sed 's/#/\n/'
Выход:
>Archaeoglobus_fulgidus_DSM_4304.gbfspecies
ATGCGCGCGATAGCTAGCTAGCTAGCTTTAGGGGGATTAGCTA----ACTCTGATTCGGA
>Ignicoccus_hospitalis_KIN4-I.gbfspecies
ATGAGTGTGACTA---TTT---GCAATCAGCTAGCTACTACGTACTGATCGTAGCTGACG
Вы можете избежать ограничения количества открытых -файлов, закрывая предыдущее имя файла всякий раз, когда изменяется имя текущего выходного файла. например.
awk '{ out=$1;
if (out != lastfile) {
if (lastfile != "") { close(lastfile) };
lastfile = out
};
print > out'
Это значительно лучше, чем закрытие файла и повторное -открытие его при каждой записи. Он закрывает файл только тогда, когда имя файла изменилось с момента последней записи. Если файл отсортирован по полю 1, ему никогда не придется повторно -открывать файл... а если он "в основном отсортирован", ему редко придется повторно -открывать файл.
Обратите внимание, :если одно и то же имя файла может встречаться более одного раза в не -смежных строках, вы должны добавить к выводу print >> out
вместо print > out
, в противном случае, когда файл Если повторно -открыт для записи, он будет полностью перезаписан -(, т.е. усечен до нулевого размера )перед этой записью.
(Кстати, это одна из причин, почему awk
не закрывает файл автоматически после каждой записи. Другая основная причина, конечно,заключается в том, что намного медленнее закрывать и повторно -открывать одни и те же файлы для каждой записи, если вам не нужно)
Это немного сложнее, если вы хотите перезаписать файл в первый раз, когда он виден в любом заданном запуске скрипта awk, но добавить, если тот же файл снова виден в том же запуске. например.
awk '{ out=$1;
if (out != lastfile) {
if (lastfile != "") { close(lastfile) };
lastfile = out
};
if (seen[out]++) {
print >> out
} else {
print > out
}'
В этой версии используется ассоциативный массив seen
для отслеживания того, видели ли мы ранее имя файла или нет. Если да, доп. если нет, перезапишите.
Я сомневаюсь, что слишком много одновременно открытых файлов действительно вызывает вашу текущую проблему, но, к вашему сведению, надежным и эффективным способом сделать то, что вы пытаетесь сделать, является следующее использование сортировки GNU для -s
и любого awk:
zcat file2split.gz |
sort -s -k1,1 |
awk '
$1 != out {
close(out)
out = $1
}
{ print > out }
'
Если у вас нет сортировки GNU, вы можете сделать то же самое с любой версией этих стандартных инструментов Unix:
zcat file2split.gz |
awk -v OFS='\t' '{print NR, $0}' |
sort -k2,2 -k1,1n |
cut -f2- |
awk '
$1 != out {
close(out)
out = $1
}
{ print > out }
'
При описанном выше подходе к сортировке входных данных до того, как awk начнет создавать выходные файлы, awk одновременно открывает только 1 выходной файл и никогда не должен открывать выходной файл более одного раза, он просто открывает его, пишет все связанные с ним строки, затем закрывает его и переходит к следующему выходному файлу.