Tengo un archivo (enorme) como este:

Archivo_test

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

Y estoy tratando de dividirlo en varios archivos en función del primer campo. Sin embargo, los valores repetidos pero no consecutivos deben crear un nuevo archivo (es decir, cada vez que el valor en el campo uno cambia respectivamente a la fila anterior, se debe generar un nuevo archivo). Entonces, en mi ejemplo anterior, filas:

a   g
a   j

Debería ir a un archivo nuevo diferente al que tiene:

a   b
a   c
a   d

Al final, tendría 4 archivos cada uno que representa uno de los cambios en el campo uno:

A.1

a   b
a   c
a   d

B.2

b   a
b   b

A.3

a   g
a   j

C.4

c   g

En realidad, también funcionaría si los identificadores son: a.1, b.1, a.2, c.1 o cualquier otro tipo de sufijo. Quiero evitar el segundo subconjunto / grupo de valores a para reemplazar / sobrescribir el archivo anterior generado con el primer grupo de valores a . Tampoco quiero que todos los valores a se agreguen al mismo archivo.

Yo sé eso:

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

Se dividiría usando la primera columna, pero también agregará los resultados al mismo archivo cuando la clave sea igual.

Para evitar este problema, estaba pensando en agregar otro campo que realmente difiera. Algo como:

Archivo_test

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

Y luego hacer:

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

Pero realmente no pude encontrar una manera, ya que creo que las matrices asociativas no funcionarán en este caso. ¿Alguna idea?

0
maria 26 feb. 2018 a las 19:36

3 respuestas

La mejor respuesta

Parece que quieres esto:

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

Pero tu pregunta no es totalmente clara.

5
Ed Morton 26 feb. 2018 a las 16:41

En Python 2.x, esto podría hacerse usando groupby de la siguiente manera:

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)

Si está utilizando 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)
1
Martin Evans 26 feb. 2018 a las 18:51

Awk realmente es más fácil, ¿no?

#!/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
hek2mgl 26 feb. 2018 a las 17:41