2011-03-01 18 views
5

Tengo un archivo con datos específicos que me gustaría extraer.Crear archivo de salida con varias líneas (Python)

El archivo tiene este aspecto:

DS User ID 1 
random garbage 
random garbage 
DS N user name 1 
random garbage 
DS User ID 2 
random garbage 
random garbage 
DS N user name 2 

Hasta ahora tengo:

import sys 
import re 
f = open(sys.argv[1]) 

strToSearch = "" 

for line in f: 
     strToSearch += line 

patFinder1 = re.compile('DS\s+\d{4}|DS\s{2}\w\s{2}\w.*|DS\s{2}N', re.MULTILINE) 

for i in findPat1: 
    print(i) 

Mi salida a la pantalla se ve así:

DS user ID 1 
DS N user name 1 
DS user ID 2 
DS N user name 2 

Si escribir en el archivo usando :

outfile = "test.dat" 
FILE = open(outfile,"a") 
FILE.writelines(line) 
FILE.close() 

Todo es empujado a una sola línea:

DS user ID 1DS N user name 1DS user ID 2DS N user name 2 

puedo vivir con el primer escenario para que la salida. Idealmente, me gustaría quitar el 'DS' y 'DS N' del archivo de salida y hacer que se separe por comas.

User ID 1,user name 1 
User ID 2, username 2 

¿Alguna idea sobre cómo lograr esto?

+2

Hola, bienvenido a StackOverflow. Tómese un minuto para familiarizarse con el editor, especialmente con el botón de Código '{}' que puede usar para formatear el código. –

+0

Esto obviamente no es su programa real. Por un lado, nunca usas la expresión regular. Tampoco coincide con las muestras que proporcionó, al menos no la mayoría de ellas. Nunca se define 'findPat1'. –

+0

Por favor, describa claramente cómo son sus datos de entrada y qué criterios está usando para que coincidan. Según sus muestras, parece que buscar líneas que comiencen con 'DS 'debería ser suficiente; si no lo es, especifique las reglas. Parece que intenta hacer coincidir las entradas de nombre de usuario/nombre de usuario correspondientes. Seguramente podemos mostrarte una mejor manera de hacerlo, si sabemos lo que estás haciendo. –

Respuesta

5

Es difícil proporcionar una solución robusta sin entender el formato de los datos de entrada real, cuánta flexibilidad se permite y cómo se usarán los datos analizados.

A partir de sólo la muestra de entrada/salida dado anteriormente, se puede cocinar rápidamente un código de ejemplo de trabajo:

out = open("test.dat", "a") # output file 

for line in open("input.dat"): 
    if line[:3] != "DS ": continue # skip "random garbage" 

    keys = line.split()[1:] # split, remove "DS" 
    if keys[0] != "N": # found ID, print with comma 
     out.write(" ".join(keys) + ",") 
    else: # found name, print and end line 
     out.write(" ".join(keys[1:]) + "\n") 

archivo de salida será:

User ID 1,user name 1 
User ID 2,user name 2 

Este código puede, por supuesto, hacerse mucho más robusto usando regex si se conoce la especificación de formato. Por ejemplo:

import re 
pat_id = re.compile(r"DS\s+(User ID\s+\d+)") 
pat_name = re.compile(r"DS\s+N\s+(.+\s+\d+)") 
out = open("test.dat", "a") 

for line in open("input.dat"): 
    match = pat_id.match(line) 
    if match: # found ID, print with comma 
     out.write(match.group(1) + ",") 
     continue 
    match = pat_name.match(line) 
    if match: # found name, print and end line 
     out.write(match.group(1) + "\n") 

Tanto los ejemplos anteriores se supone que "ID de usuario X" siempre viene antes de "N nombre de usuario X", por lo tanto, los respectivos caracteres de salida de la "" y '\ n'.

Si la orden no es específica, se pueden almacenar los valores en un diccionario utilizando la ID numérica como clave y luego imprimir el par ID/nombre una vez que se haya analizado toda la entrada.

Si proporciona más información, tal vez podamos ser de más ayuda.

+0

Funciona muy bien y es exactamente lo que necesitaba. Gracias. Intentando eliminar el DS y el DS N, será perfecto. – user639302

+0

Excelente truco: explicación increíblemente útil. – mbb

4

print agrega un carácter de nueva línea después de los argumentos, pero writelines no lo hace. Así que hay que escribir como:

file = open(outfile, "a") 
file.writelines((i + '\n' for i in findPat1)) 
file.close() 

La declaración writelines también se puede escribir como:

for i in findPat1: 
    file.write(i + '\n') 
+0

nice one, +1 de mí. – doug

1
FILE.writelines(line) 

no agrega separadores de línea.

Just Do:

FILE.write(line + "\n") 

O:

FILE.write("\n".join(lines)) 
0
import re 

ch ='''\ 
DS User ID 1 
random garbage 
random garbage 
DS N user name 1 
random garbage 
DS User ID 2 
random garbage 
random garbage 
DS N user name 2''' 

RE = '^DS (User ID (\d+)).+?^DS N(user name \\2)' 

with open('outputfile.txt','w') as f: 
    for match in re.finditer(RE,ch,re.MULTILINE|re.DOTALL): 
     f.write(','.join(match.groups())+'\n') 

EDIT:

reemplazado

RE = '^DS (User ID \d+).+?^DS N(user name \d+)' 

con

RE = '^DS (User ID (\d+)).+?^DS N(user name \\2)' 
Cuestiones relacionadas