根据字段拆分大文件,并为每个文件添加唯一标识符

时间:2018-02-26 16:36:49

标签: python bash unix awk sed

我有一个(巨大的)这样的文件:

test_file里面

a   b
a   c
a   d
b   a
b   b
a   g
a   j
c   g

我正在尝试根据第一个字段将其拆分为多个文件。但是,重复但不连续的值应该创建一个新文件(即,每当字段1中的值相应于前一行改变时,应该生成一个新文件)。因此,在我之前的示例中,行:

a   g
a   j

应该转到与以下文件不同的新文件:

a   b
a   c
a   d

最后,我将有4个文件,每个文件代表第一个字段中的一个变化:

A.1

a   b
a   c
a   d

B.2

b   a
b   b

A.3

a   g
a   j

C.4

c   g

实际上,如果标识符是:a.1,b.1,a.2,c.1或任何其他类型的后缀,它也会起作用。我想避免使用 a 值的第二个子集/组来替换/覆盖使用第一组 a 值生成的先前文件。我也不希望所有 a 值都附加到同一个文件中。

我知道:

awk '{print > $1; close( $1)}' test_file

将使用第一列进行拆分,但当密钥相等时,它也会将结果附加到同一文件中。

为了避免这个问题,我想添加另一个真正不同的字段。类似的东西:

test_file里面

1    a  b
1    a  c
1    a  d
2    b  a
2    b  b
3    a  g
3    a  j
4    c  g

然后做:

 awk '{print > $1"_"$2; close( $1"_"$2) }' test_file

但我真的找不到方法,因为我认为关联数组在这种情况下不起作用。任何的想法?

3 个答案:

答案 0 :(得分:5)

听起来你可能想要这个:

awk '$1!=prev{ close(out); out="File_"$1"."(++cnt); prev=$1 } { print > out }' test_file

但你的问题并不完全清楚。

答案 1 :(得分:2)

Awk真的很容易,不是吗?

#!/usr/bin/env python
files_count = 1
first_col = None
with open('maria.txt') as maria:
    for line in maria:
        line = line.rstrip()
        columns = line.split()
        if columns[0] == first_col:
            print (line, file=current_out)
        else:
            first_col = columns[0]
            current_out = open(first_col+'.'+str(files_count), 'w')
            files_count+=1
            print (line, file=current_out)

答案 2 :(得分:1)

在Python 2.x中,可以使用groupby完成此操作,如下所示:

import csv
from itertools import groupby

with open('huge.txt', 'rb') as f_input:
    csv_input = csv.reader(f_input, delimiter=' ', skipinitialspace=True)

    for index, (k, g) in enumerate(groupby(csv_input, lambda x: x[0]), start=1):
        with open('{}.{}'.format(k, index), 'wb') as f_output:
            csv.writer(f_output, delimiter=' ').writerows(g)

如果您使用的是Python 3.x:

import csv
from itertools import groupby

with open('huge.txt', 'r', newline='') as f_input:
    csv_input = csv.reader(f_input, delimiter=' ', skipinitialspace=True)

    for index, (k, g) in enumerate(groupby(csv_input, lambda x: x[0]), start=1):
        with open('{}.{}'.format(k, index), 'w', newline='') as f_output:
            csv.writer(f_output, delimiter=' ').writerows(g)