2012-10-11 55 views
8

Estoy tratando de analizar un archivo de prueba. el archivo tiene nombre de usuario, dirección y teléfono en el siguiente formato:Líneas de análisis de datos del archivo de texto y salida como columnas

Name: John Doe1 
address : somewhere 
phone: 123-123-1234 

Name: John Doe2 
address : somewhere 
phone: 123-123-1233 

Name: John Doe3 
address : somewhere 
phone: 123-123-1232 

Sólo durante casi 10k usuarios:) lo que me gustaría hacer es convertir esas filas de columnas, por ejemplo:

Name: John Doe1    address : somewhere   phone: 123-123-1234 
Name: John Doe2    address : somewhere   phone: 123-123-1233 
Name: John Doe3    address : somewhere   phone: 123-123-1232 

Preferiría hacerlo en bash pero si sabes cómo hacerlo en python también sería genial, el archivo que tiene esta información está en/root/docs/information. Cualquier consejo o ayuda sería muy apreciado.

+2

¿Qué has probado? – nneonneo

+0

Buena pregunta inicial, @tafiela. Pero no olvide señalar las siguientes preguntas sobre lo que ha intentado hacer. – Yamaneko

+0

¿La dirección es realmente solo una línea después de los dos puntos? –

Respuesta

5

Una forma con GNU awk:

awk 'BEGIN { FS="\n"; RS=""; OFS="\t\t" } { print $1, $2, $3 }' file.txt 

Resultados:

Name: John Doe1  address : somewhere  phone: 123-123-1234 
Name: John Doe2  address : somewhere  phone: 123-123-1233 
Name: John Doe3  address : somewhere  phone: 123-123-1232 

Tenga en cuenta que he establecido el separador de archivos de salida (OFS) en dos caracteres de tabulación (\t\t). Puede cambiar esto a cualquier personaje o conjunto de caracteres que desee. HTH.

+0

+1 - me ganaste al golpe. –

+0

¿Qué hace 'RS'? – Yamaneko

+1

@VictorHugo: 'RS' es la abreviatura de separador de registros. Por defecto, 'RS' está configurado a' \ n' o nueva línea. Esto permite 'awk' procesar el archivo línea por línea. Cuando lo configuramos en nada (o '" "'), en realidad estamos cambiando la definición de 'awk' de una línea. Dado que cada uno de los registros está separado por líneas vacías, al establecer 'RS =" "' se obtiene una solución fácil. HTH. – Steve

0

En Python:

results = [] 
cur_item = None 

with open('/root/docs/information') as f: 
    for line in f.readlines(): 
     key, value = line.split(':', 1) 
     key = key.strip() 
     value = value.strip() 

     if key == "Name": 
      cur_item = {} 
      results.append(cur_item) 
     cur_item[key] = value 

for item in results: 
    # print item 
+0

Debe precisar el idioma;) –

+0

@sputnick No soy del todo Entiendo lo que quiere decir –

+0

Simplemente diga el idioma: Es Python. – Matthias

0

Usted debe ser capaz de analizar esto utilizando el método split() en una cadena:

line = "Name: John Doe1" 
key, value = line.split(":") 
print(key) # Name 
print(value) # John Doe1 
3

Con un corto Perl de una sola línea:

$ perl -ne 'END{print "\n"}chomp; /^$/ ? print "\n" : print "$_\t\t"' file.txt 

SALIDA

Name: John Doe1   address : somewhere    phone: 123-123-1234 
Name: John Doe2   address : somewhere    phone: 123-123-1233 
Name: John Doe3   address : somewhere    phone: 123-123-1232 
1

Esto parece hacer básicamente lo que quiere:

information = 'information' # file path 

with open(information, 'rt') as input: 
    data = input.read() 

data = data.split('\n\n') 

for group in data: 
    print group.replace('\n', '  ') 

Salida:

Name: John Doe1  address : somewhere  phone: 123-123-1234 
Name: John Doe2  address : somewhere  phone: 123-123-1233 
Name: John Doe3  address : somewhere  phone: 123-123-1232  
0

Se puede recorrer a través de líneas e imprimirlos en columnas como esto -

for line in open("/path/to/data"): 
    if len(line) != 1: 
     # remove \n from line's end and make print statement 
     # skip the \n it adds in the end to continue in our column 
     print "%s\t\t" % line.strip(), 
    else: 
     # re-use the blank lines to end our column 
     print 
2

El uso de pasta, podemos unir las líneas en el archivo:

$ paste -s -d"\t\t\t\n" file 
Name: John Doe1 address : somewhere  phone: 123-123-1234 
Name: John Doe2 address : somewhere  phone: 123-123-1233 
Name: John Doe3 address : somewhere  phone: 123-123-1232 
+0

No tan bien formateado =) –

+0

@sputnick Cierto, pero esto tiene la parte difícil. Hay innumerables utilidades para expandir pestañas. –

+0

Sí, pero en este caso, necesita 2 tubos;) –

1

Sé que no ha mencionado awk, pero que resuelve su problema bien:

awk 'BEGIN {RS="";FS="\n"} {print $1,$2,$3}' data.txt 
0
#!/usr/bin/env python 

def parse(inputfile, outputfile): 
    dictInfo = {'Name':None, 'address':None, 'phone':None} 
    for line in inputfile: 
    if line.startswith('Name'): 
     dictInfo['Name'] = line.split(':')[1].strip() 
    elif line.startswith('address'): 
     dictInfo['address'] = line.split(':')[1].strip() 
    elif line.startswith('phone'): 
     dictInfo['phone'] = line.split(':')[1].strip() 
     s = 'Name: '+dictInfo['Name']+'\t'+'address: '+dictInfo['address'] \ 
      +'\t'+'phone: '+dictInfo['phone']+'\n' 
     outputfile.write(s) 

if __name__ == '__main__': 
    with open('output.txt', 'w') as outputfile: 
    with open('infomation.txt') as inputfile: 
     parse(inputfile, outputfile) 
0

Una solución que usa sed.

cat input.txt | sed '/^$/d' | sed 'N; s:\n:\t\t:; N; s:\n:\t\t:' 
  1. primer tubo, sed '/^$/d', elimina las líneas en blanco.
  2. Segundo tubo, sed 'N; s:\n:\t\t:; N; s:\n:\t\t:', combina las líneas.
 
Name: John Doe1  address : somewhere  phone: 123-123-1234 
Name: John Doe2  address : somewhere  phone: 123-123-1233 
Name: John Doe3  address : somewhere  phone: 123-123-1232 
1

La mayoría de las soluciones aquí son sólo cambio de formato de los datos en el archivo que está leyendo. Tal vez eso es todo lo que quieres.

Si realmente desea analizar los datos, colóquelos en una estructura de datos.

Este ejemplo en Python:

data="""\ 
Name: John Doe2 
address : 123 Main St, Los Angeles, CA 95002 
phone: 213-123-1234 

Name: John Doe1 
address : 145 Pearl St, La Jolla, CA 92013 
phone: 858-123-1233 

Name: Billy Bob Doe3 
address : 454 Heartland St, Mobile, AL 00103 
phone: 205-123-1232""".split('\n\n')  # just a fill-in for your file 
              # you would use `with open(file) as data:` 

addr={} 
w0,w1,w2=0,0,0    # these keep track of the max width of the field 
for line in data: 
    fields=[e.split(':')[1].strip() for e in [f for f in line.split('\n')]] 
    nam=fields[0].split() 
    name=nam[-1]+', '+' '.join(nam[0:-1]) 
    addr[(name,fields[2])]=fields 
    w0,w1,w2=[max(t) for t in zip(map(len,fields),(w0,w1,w2))] 

Ahora usted tiene la libertad para ordenar, cambiar el formato, puesto en la base de datos, etc.

Esto imprime el formato con el que los datos, ordenados:

for add in sorted(addr.keys()): 
    print 'Name: {0:{w0}} Address: {1:{w1}} phone: {2:{w2}}'.format(*addr[add],w0=w0,w1=w1,w2=w2) 

Lienzo:

Name: John Doe1  Address: 145 Pearl St, La Jolla, CA 92013 phone: 858-123-1233 
Name: John Doe2  Address: 123 Main St, Los Angeles, CA 95002 phone: 213-123-1234 
Name: Billy Bob Doe3 Address: 454 Heartland St, Mobile, AL 00103 phone: 205-123-1232 

Eso está ordenado por el apellido, nombre usado en la clave dict.

Ahora imprimirlo ordenadas según el código de área:

for add in sorted(addr.keys(),key=lambda x: addr[x][2]): 
    print 'Name: {0:{w0}} Address: {1:{w1}} phone: {2:{w2}}'.format(*addr[add],w0=w0,w1=w1,w2=w2) 

Lienzo:

Name: Billy Bob Doe3 Address: 454 Heartland St, Mobile, AL 00103 phone: 205-123-1232 
Name: John Doe2  Address: 123 Main St, Los Angeles, CA 95002 phone: 213-123-1234 
Name: John Doe1  Address: 145 Pearl St, La Jolla, CA 92013 phone: 858-123-1233 

Pero, ya que tienes los datos en un diccionario indexado, se puede imprimir como una tabla en lugar ordenado por código postal:

# print table header 
print '|{0:^{w0}}|{1:^{w1}}|{2:^{w2}}|'.format('Name','Address','Phone',w0=w0+2,w1=w1+2,w2=w2+2) 
print '|{0:^{w0}}|{1:^{w1}}|{2:^{w2}}|'.format('----','-------','-----',w0=w0+2,w1=w1+2,w2=w2+2) 
# print data sorted by last field of the address - probably a zip code 
for add in sorted(addr.keys(),key=lambda x: addr[x][1].split()[-1]): 
    print '|{0:>{w0}}|{1:>{w1}}|{2:>{w2}}|'.format(*addr[add],w0=w0+2,w1=w1+2,w2=w2+2) 

Lienzo:

|  Name  |    Address    | Phone  | 
|  ----  |    -------    | -----  | 
| Billy Bob Doe3| 454 Heartland St, Mobile, AL 00103| 205-123-1232| 
|  John Doe1| 145 Pearl St, La Jolla, CA 92013| 858-123-1233| 
|  John Doe2| 123 Main St, Los Angeles, CA 95002| 213-123-1234| 
Cuestiones relacionadas