2016-02-02 4 views
0

У меня есть файл, который я хотел бы разбить на несколько файлов с значениями uniq для первого столбца. Например, вот файл:значения расщепления на основе значений в определенном столбце

fileA.txt

1 Cat 
1 Dog 
1 Frog 
2 Boy 
2 Girl 
3 Tree 
3 Leaf 
3 Branch 
3 Trunk 

Я хотел бы мой выход выглядеть примерно так:

file1.txt

1 Cat 
2 Boy 
3 Tree 

file2.txt

1 Dog 
2 Girl 
3 Leaf 

fi le3.txt

1 Frog 
3 Branch 

file4.txt

3 Trunk 

Если значение не существует, я хочу, чтобы это было пропущено. Я попытался найти похожие ситуации для себя, но я пришел в себя. Кто-нибудь знает, как это сделать?

Теоретически эта команда awk должна работать: awk '{print > "file" ++a[$1] ".txt"}' input. Однако я не могу заставить его работать должным образом (скорее всего, из-за того, что я работаю на mac) Кто-нибудь знает об альтернативном пути?

+2

@EdMorton, которая была проблема. Спасибо! – interstellar

ответ

3

Несправедливое выражение в правой части перенаправления выходного сигнала является неопределенным поведением. Попробуйте awk '{print > ("file" ++a[$1] ".txt")}' input.

Если иметь слишком много открытых файлов одновременно является проблемой, то получить GNU AWK, но если вы не можете:

$ ls 
fileA.txt 

$ awk '{f="file" ++a[$1] ".txt"; print >> f; close(f)}' fileA.txt 

$ ls 
file1.txt file2.txt file3.txt file4.txt fileA.txt 

$ cat file1.txt 
1 Cat 
2 Boy 
3 Tree 
+0

Я заметил, что, когда я использую это, я получаю сообщение об ошибке. 'awk: file18.txt делает слишком много открытых файлов входной номер записи 19, файл input.txt номер исходной строки 1' Вы знаете, есть ли способ закрыть файлы по мере чтения моего фактического файла? Может быть, 'awk '{print >> (" file "++ a [$ 1]" .txt ")}' input'? – interstellar

+0

@interstellar В AWK '>' и '>>' немного отличаются от оболочек, таких как bash. Оба 'print>' и 'print >>' будут добавляться к файлу каждый раз, когда эта строка будет выполнена. Разница в том, что происходит при первом запуске линии. При первом запуске 'print>' он обрезает файл до нуля, затем добавляет к нему (и каждый последующий раз). 'print >>' будет добавляться без обрезания в первый раз. Вы хотите, чтобы AWK создавал свежий результат и не сохранял все, что у вас было раньше, поэтому '' 'подходит в ответе @ EdMorton. – e0k

+0

@interstellar, конечно, просто вызывайте close(). Если вы используете GNU awk, у вас не будет этой проблемы, так как он будет управлять состояниями файлов внутри. Я отредактировал свой ответ, чтобы показать, как добавить close(). –

2

Вот решение в Python:

from collections import Counter 
fd_dict = {} 
ind_counter = Counter() 

with open('fileA.txt') as inf: 
    for line in inf: 
     ind, _ = line.split() 
     ind_counter[ind] += 1 
     file_ind = ind_counter[ind] 
     fd = (
      fd_dict[file_ind] if file_ind in fd_dict else 
      fd_dict.setdefault(
       file_ind, 
       open('file{}.txt'.format(file_ind), 'w'))) 
     fd.write(line) 

for fd in fd_dict.itervalues(): 
    fd.close() 
Смежные вопросы