Самый быстрый способ сортировки текстового файла по образцу идентификаторов
Мне нужно отсортировать файл mwe.txt:
>gb|LOEQ01000001.1|
1 CC|1 CC|1 NN|0 NN|0 NN|0 CC|1 NN|0 CC|1 CC|1 CC|1
2 AA|1 AA|1 NN|0 NN|0 NN|0 AA|1 NN|0 AA|1 AA|1 AA|1
>gb|LOEQ01000181.1|
1 CC|1 CC|1 NN|0 NN|0 NN|0 CC|1 NN|0 CC|1 CC|1 CC|1
>gb|LOEQ01000131.1|
1 CC|1 CC|1 NN|0 NN|0 NN|0 CC|1 NN|0 CC|1 CC|1 CC|1
2 AA|1 AA|1 NN|0 NN|0 NN|0 AA|1 NN|0 AA|1 AA|1 AA|1
3 AA|1 AA|1 NN|0 NN|0 NN|0 AA|1 NN|0 AA|1 AA|1 AA|1
по образцу идентификаторов в names.txt:
LOEQ01000001.1
LOEQ01000131.1
LOEQ01000181.1
Я смог добиться этого с помощью sed и awk:
for f in $(cat names.txt); do sed -n -e "/$f|/,/>/ p" mwe.txt | awk '/>/&&c++>0 {next} 1' >> sorted.txt; done
Что приводит к:
>gb|LOEQ01000001.1|
1 CC|1 CC|1 NN|0 NN|0 NN|0 CC|1 NN|0 CC|1 CC|1 CC|1
2 AA|1 AA|1 NN|0 NN|0 NN|0 AA|1 NN|0 AA|1 AA|1 AA|1
>gb|LOEQ01000131.1|
1 CC|1 CC|1 NN|0 NN|0 NN|0 CC|1 NN|0 CC|1 CC|1 CC|1
2 AA|1 AA|1 NN|0 NN|0 NN|0 AA|1 NN|0 AA|1 AA|1 AA|1
3 AA|1 AA|1 NN|0 NN|0 NN|0 AA|1 NN|0 AA|1 AA|1 AA|1
>gb|LOEQ01000181.1|
1 CC|1 CC|1 NN|0 NN|0 NN|0 CC|1 NN|0 CC|1 CC|1 CC|1
Фактические файлы, которые я использую, имеют размер>120 ГБ, и мое решение действительно неэффективно. Я предполагаю, что возможно использовать алгоритм рекурсивной сортировки слиянием, но я не уверен, как организовать входные данные, чтобы их можно было сортировать, в основном из-за несовместимого количества строк для каждого образца / идентификатора. Кто-нибудь может предложить более быстрый путь?
1 ответ
$ cat tst.awk
BEGIN { FS="|" }
NR==FNR { keys[++numKeys] = $0; next }
/^>/ { key = $2 }
{ block[key] = block[key] $0 ORS }
END {
for (keyNr=1; keyNr<=numKeys; keyNr++) {
key = keys[keyNr]
printf "%s", block[key]
}
}
$ awk -f tst.awk names.txt mwe.txt
>gb|LOEQ01000001.1|
1 CC|1 CC|1 NN|0 NN|0 NN|0 CC|1 NN|0 CC|1 CC|1 CC|1
2 AA|1 AA|1 NN|0 NN|0 NN|0 AA|1 NN|0 AA|1 AA|1 AA|1
>gb|LOEQ01000131.1|
1 CC|1 CC|1 NN|0 NN|0 NN|0 CC|1 NN|0 CC|1 CC|1 CC|1
2 AA|1 AA|1 NN|0 NN|0 NN|0 AA|1 NN|0 AA|1 AA|1 AA|1
3 AA|1 AA|1 NN|0 NN|0 NN|0 AA|1 NN|0 AA|1 AA|1 AA|1
>gb|LOEQ01000181.1|
1 CC|1 CC|1 NN|0 NN|0 NN|0 CC|1 NN|0 CC|1 CC|1 CC|1
Это будет быстрее, но это означает, что вам нужно сохранить весь файл в памяти, так что попробуйте и посмотрите, если это проблема. Если это так, вы можете взять подмножество имен ключей одновременно и использовать что-то вроде этого сценария:
$ cat tst.awk
BEGIN { FS="|" }
NR==FNR { keys[++numKeys] = $0; tgtKeys[$0]; next }
/^>/ { key = $2 }
key in tgtKeys { block[key] = block[key] $0 ORS }
END {
for (keyNr=1; keyNr<=numKeys; keyNr++) {
key = keys[keyNr]
printf "%s", block[key]
}
}
< names.txt xargs -n 1000 echo | awk -f tst.awk - mwe.txt
который будет печатать строку из mwe.txt 1000 за один раз.