2012-02-17 2 views
1

Я должен выполнить простую задачу, но я не знаю, как это сделать, и я поставлен в очередь. Мне нужно пересыпать линии двух разных файлов каждые 4 линии:пересекают линии двух разных файлов.

Файл 1:

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 

FILE 2:

A 
B 
C 
D 
E 
F 
G 
H 
I 
J 
K 
L 

Желаемый результат:

1 
2 
3 
4 
A 
B 
C 
D 
5 
6 
7 
8 
E 
F 
G 
H 
9 
10 
11 
12 
I 
J 
K 
L 

Я ищу сценарий sed, awk или python или любую другую команду bash.

Спасибо за ваше время!

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

import sys 
from Bio import SeqIO 
from Bio.Seq import Seq 
from Bio.SeqRecord import SeqRecord 


def main(forward,reverse): 

    for F, R in zip (SeqIO.parse(forward, "fastq"), SeqIO.parse(reverse, "fastq")): 

     fastq_out_F = SeqRecord(F.seq, id = F.id, description = "") 
     fastq_out_F.letter_annotations["phred_quality"] = F.letter_annotations["phred_quality"] 

     fastq_out_R = SeqRecord(R.seq, id = R.id, description = "") 
     fastq_out_R.letter_annotations["phred_quality"] = R.letter_annotations["phred_quality"] 

     print fastq_out_F.format("fastq"), 
     print fastq_out_R.format("fastq"), 


if __name__ == '__main__': 
    main(sys.argv[1], sys.argv[2]) 
+5

Как насчет совершения покупок? – Gerrat

+1

Как сказал Джеррат [EDIT: и Рик Погги]: Покажите нам, что вы пробовали. Вы вряд ли получите большую помощь (и особенно маловероятно, чтобы получить его от лучших людей), если вы просто попросите Stack Overflow выполнить вашу работу за вас. Продемонстрируйте, что вы совершили настоящую попытку самостоятельно, и вы не только покажете, что вы просите добросовестно, но и разъясните, где трудности. –

+0

Я пытался сделать это с помощью конкретных библиотек python для анализа моих файлов ... – Geparada

ответ

3

Это может работать для вас: (с помощью GNU СЭД)

sed -e 'n;n;n;R file2' -e 'R file2' -e 'R file2' -e 'R file2' file1 

или с использованием пасты/Баш:

paste -d' ' <(paste -sd' \n' file1) <(paste -sd' \n' file2) | tr ' ' '\n' 

или:

parallel -N4 --xapply 'printf "%s\n%s\n" {1} {2}' :::: file1 :::: file2 
+0

+1 Очень творческий! – kev

+0

Благодаря @kev на отражении xargs также может обеспечить решение. – potong

0

Код, который вы опубликовали, выглядит чрезвычайно сложным. Существует эмпирическое правило: программирование: всегда есть более простое решение. В вашем случае проще.

Первое, что вам нужно сделать, это определить ограничения ввода. Собираетесь ли вы обрабатывать действительно большие файлы? Или они будут только размером один или два килобайта? Это важно.

Вторая вещь: посмотрите на tools you have. С Python у вас есть file objects, lists, generators и так далее. Попытайтесь объединить эти инструменты для получения желаемого результата.

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

Взгляните на the file object, xrange, list slicing и list comprehensions. Если вы предпочитаете делать это класс, вы также можете взглянуть на модуль itertools.

0

Попробуйте это, изменив соответствующий значения имени файла для f1 и f2.

awk 'BEGIN{ 
    sectionSize=4; maxSectionCnt=sectionSize; maxSectionCnt++ 
    notEof1=notEof2=1 
    f1="file1" ; f2="file2" 
    while (notEof1 && notEof2) { 
    if (notEof1) { 
     for (i=1;i<maxSectionCnt;i++) { 
     if (getline <f1>0) { print "F1:" i":" $0 } else {notEof1=0} 
     } 
    } 
    if (notEof2) { 
     for (i=1;i<maxSectionCnt;i++) { 
     if (getline <f2>0) { print "F2:" i":" $0 } else {notEof2=0} 
     } 
    } 
    } 
}' 

Вы также можете удалить и т.д. заголовок записи в "F1: i":". Я добавил, что помогает отлаживать код.

Как Pastafarianist справедливо указывает, возможно, потребуется изменить это, если у вас есть ожидания относительно того, что будет происходить, если файлы не одинакового размера, и т.д.

Я надеюсь, что это помогает.

1

Это может быть сделано в чистом Баш:

f1=""; f2="" 
while test -z "$f1" -o -z "$f2"; do 
    { read LINE && echo "$LINE" && \ 
     read LINE && echo "$LINE" && \ 
     read LINE && echo "$LINE" && \ 
     read LINE && echo "$LINE"; } || f1=end; 
    { read -u 3 LINE && echo "$LINE" && \ 
     read -u 3 LINE && echo "$LINE" && \ 
     read -u 3 LINE && echo "$LINE" && \ 
     read -u 3 LINE && echo "$LINE"; } || f2=end; 
done < f1 3< f2 

Идея заключается в том, чтобы использовать новый дескриптор файла (3 в данном случае) и читать из stdin и этот дескриптор файла одновременно.

1

Смесь paste и sed также может быть использована, если вы не имеете GNU sed:

paste -d '\n' f1 f2 | sed -e 'x;N;x;N;x;N;x;N;x;N;x;N;x;N;s/^\n//;H;s/.*//;x' 

Если вы не знакомы с sed, есть второй буфер называется трюма, где вы можете сохранить данные. Команда x обменивает текущий буфер с пространством удержания, команда N добавляет одну строку в текущий буфер, а команда H добавляет текущий буфер в пространство удержания.

Так первый x;N сохранить текущую строку (от f1 из-за paste) в трюме и прочитать следующую строку (от f2 из-за paste), то каждый x;N;x;N читать новую линию от f1 и f2, и завершение скрипта путем удаления новой строки из 4 строк f2, помещает строки из f2 в конец строк f1, очищает пространство удержания для следующего прогона и печатает 8 строк.

Смежные вопросы