2016-12-13 3 views
2

Я работаю с большим количеством файлов с этой структурой:Разбиение файлов на несколько файлов на основе какой-то шаблон и взять какую-то информацию

BEGIN 
TITLE=id=PRD000012;PRIDE_Exp_Complete_Ac_1645.xml;spectrum=1393 
PEPMASS=946.3980102539062 
CHARGE=3.0+ 
USER03= 
SEQ=DDDIAAL 
TAXONOMY=9606 
272.228 126847.000 
273.252 33795.000 
END 

BEGIN IONS 
TITLE=id=PRD000012;PRIDE_Exp_Complete_Ac_1645.xml;spectrum=1383 
PEPMASS=911.3920288085938 
CHARGE=2.0+ 
USER03= 
SEQ=QGKFEAAETLEEAAMR 
TAXONOMY=9606 
1394.637 71404.000 
1411.668 122728.000 
END 

BEGIN IONS 
TITLE=id=PRD000012;PRIDE_Exp_Complete_Ac_1645.xml;spectrum=2965 
PEPMASS=946.3900146484375 
CHARGE=3.0+ 
TAXONOMY=9606 
1564.717 92354.000 
1677.738 33865.000 
END 

Эта структура повторяется тысячи раз, но с разными данными внутри. Как вы можете видеть, между некоторыми начинающими, иногда SEQ и USER03 там нет. Это потому, что белок не идентифицирован ... И вот моя проблема.

Я хотел бы знать, сколько белков идентифицировано и сколько неизвестно. Чтобы сделать это, я пытался это:

for i in $(ls *.txt); do 
    echo $i 

    awk '/^BEGIN/{n++;w=1} n&&w{print > "./cache/out" n ".txt"} /^END/{w=0}' $i 

done 

Я нашел это здесь (Split a file into multiple files based on a pattern and name the new files by the search pattern in Unix?)

И затем использовать выходы и классифицировать их:

for i in $(ls cache/*.txt); do 
    echo $i 

    if grep -q 'SEQ' $i; then 
     mv $i ./archive_identified 
    else 
     mv $i ./archive_unidentified 
    fi 
done 

После этого, я хотел бы взять некоторые данные (пример: спектр, USER03, SEQ, TAXONOMY) из секретных файлов.

for I in $(ls archive_identified/*.txt); do 
    echo $i 
    grep 'SEQ' $i | cut -d "=" -f2- | tr ',' '\n' >> ./sequences_ide.txt 
    grep 'TAXONOMY' $i | cut -d "=" -f2- | tr ',' '\n' >> ./taxonomy_ide.txt 
    grep 'USER' $i | cut -d "=" -f2- >> ./modifications_ide.txt 
    grep 'TITLE' $i | sed 's/^.*\(spectrum.*\)/\1/g' | cut -d "=" -f2- >> ./spectrum.txt 

done 

for i in $(ls archive_unidentified/*.txt); do 
    echo $i 
    grep 'SEQ' $i | cut -d "=" -f2- | tr ',' '\n' >> ./sequences_unide.txt 
    grep 'TAXONOMY' $i | cut -d "=" -f2- | tr ',' '\n' >> ./taxonomy_unide.txt 
    grep 'USER' $i | cut -d "=" -f2- >> ./modifications_unide.txt 
    grep 'TITLE' $i | sed 's/^.*\(spectrum.*\)/\1/g' | cut -d "=" -f2- >> ./spectrum_unide.txt 

done 

Проблема в том, что первая часть скрипта занимает слишком много времени из-за большого размера данных (12-15 гб). Есть ли способ сделать это проще?

Заранее спасибо.

+0

Используйте 'awk' для преобразования каждой записи в CSV данных столбца : SEQ, TAXONOMY, USER, TITLE. Затем используйте 'grep', чтобы разбить этот файл на два: те, у которых есть и без SEQ. Затем используйте 'cut', чтобы вытащить столбцы в отдельные файлы. Альтернативно: просто сделайте все это в 'awk'. – bishop

+0

@bishop Не могли бы вы дать мне несколько подсказок, как я могу это сделать? Я никогда не работал с csv-файлами. – Enrique

+0

Не требуется для CSV: любой ad-hoc формат будет делать. Хитрость заключается в том, чтобы повернуть ваши ориентированные на строки записи в формат, ориентированный на столбцы, потому что вы «работаете против зерна» с исходным форматом данных. – bishop

ответ

2

Вы можете сделать все в одном awk скрипт. awk может проходить через все строки (записи), поэтому вам не нужен внешний цикл. Например, для файла данных вы предоставили

$ awk -v RS= '/\nSEQ/ {seq++; print > "file_path_with_seq" NR ".txt"; next} 
         {noseq++; print > "file_path_without_seq" NR ".txt"} 
       END {   print "with seq:", seq; 
           print "without seq:", noseq}' file 

напечатает

with seq: 2 
without seq: 1 

и производит файлы

$ head file_path_with* 

==> file_path_with_seq1.txt <== 
BEGIN 
TITLE=id=PRD000012;PRIDE_Exp_Complete_Ac_1645.xml;spectrum=1393 
PEPMASS=946.3980102539062 
CHARGE=3.0+ 
USER03= 
SEQ=DDDIAAL 
TAXONOMY=9606 
272.228 126847.000 
273.252 33795.000 
END 

==> file_path_with_seq2.txt <== 
BEGIN IONS 
TITLE=id=PRD000012;PRIDE_Exp_Complete_Ac_1645.xml;spectrum=1383 
PEPMASS=911.3920288085938 
CHARGE=2.0+ 
USER03= 
SEQ=QGKFEAAETLEEAAMR 
TAXONOMY=9606 
1394.637 71404.000 
1411.668 122728.000 
END 

==> file_path_without_seq3.txt <== 
BEGIN IONS 
TITLE=id=PRD000012;PRIDE_Exp_Complete_Ac_1645.xml;spectrum=2965 
PEPMASS=946.3900146484375 
CHARGE=3.0+ 
TAXONOMY=9606 
1564.717 92354.000 
1677.738 33865.000 
END 
+0

Мое беспокойство сводилось бы к минимуму ввода-вывода, в общем, как к источнику 12 ГБ, что будет много накладных расходов. +1 – bishop

+0

@karakfa Wow ... Ваш ответ действительно верный и отлично работает – Enrique

+0

Как я уже упоминал много раз раньше, результат не вставляя в скобки выражение, правая сторона перенаправления вывода - это неопределенное поведение, так что некоторые awks WILL терпят неудачу с ' print> "file_path_with_seq" NR ".txt". Просто скопируйте его, и он будет работать во всех awks и имеет немного лучшую читаемость: 'print> (" file_path_with_seq "NR" .txt ")'. С awks, отличным от GNU awk, вам придется закрывать предыдущие файлы, так как вы идете слишком, чтобы вам было лучше с 'close (seqOut); seqOut = "file_path_with_seq" NR ".txt"; print> seqOut' для 100% переносимости для всех awks. –