2015-07-10 13 views
5

Sto tentando di analizzare l'output dal comando mdls di OS X. Per alcune chiavi, il valore è un elenco di valori. Devo catturare correttamente queste coppie di valori e valori. Tutti gli elenchi di valori iniziano con ( e terminano con ).Sostituire in modo efficiente stringhe di elenchi di righe multiple con stringa elenco di righe singole

Devo essere in grado di scorrere tutte le coppie di valori, in modo da poter analizzare correttamente più uscite (ad esempio, mdls eseguire su più file per produrre un singolo output, dove non c'è distinzione tra dove finisce il metadata di un file e inizia l'altro). Ho qualche codice di esempio qui sotto.

Esiste un modo più efficiente per farlo?

import re 

mdls_output = """kMDItemAuthors     = (
    margheim 
) 
kMDItemContentCreationDate  = 2015-07-10 14:41:01 +0000 
kMDItemContentModificationDate = 2015-07-10 14:41:01 +0000 
kMDItemContentType    = "com.adobe.pdf" 
kMDItemContentTypeTree   = (
    "com.adobe.pdf", 
    "public.data", 
    "public.item", 
    "public.composite-content", 
    "public.content" 
) 
kMDItemCreator     = "Safari" 
kMDItemDateAdded    = 2015-07-10 14:41:01 +0000 
""" 

mdls_lists = re.findall(r"^\w+\s+=\s\(\n.*?\n\)$", mdls_output, re.S | re.M) 
single_line_lists = [re.sub(r'\s+', ' ', x.strip()) for x in mdls_lists] 
for i, mdls_list in enumerate(mdls_lists): 
    mdls_output = mdls_output.replace(mdls_list, single_line_lists[i]) 
print(mdls_output) 
+0

La soluzione funziona? Stai chiedendo un'alternativa efficiente in memoria o una soluzione * più veloce *? – wwii

+0

Funziona, ma sembra inutilmente complesso. Voglio * nidificare due 're.sub's, ma non ho potuto farlo funzionare; cioè, sostituire la lista multilinea per una lista a riga singola, che richiederebbe la normalizzazione degli spazi bianchi (ad esempio 're.sub (r"^\ w + \ s + = \ s \ (\ n. *? \ n \) $ " , re.sub (r '\ s +', '', '\ 1'.strip(), mdls_output) ') – smargh

+0

Sembra quasi ok, ma la tua espressione regolare principale è un po' errata. Probabilmente dovrebbe essere" "^ \ w + \ s * = \ s * \ (\ n. *? \ n \) $ "' Non dovrebbe essere 'mdls_output = mdls_output.replace (mdls_list [i], single_line_lists [i])'? – sln

risposta

2

È possibile usufruire di regex sostituto del pitone che può richiedere una funzione come stringa di sostituzione. La funzione viene chiamata per ogni corrispondenza con l'oggetto della corrispondenza. La stringa restituita sostituisce la corrispondenza.

def myfn(m): 
    return re.sub(r'\s+', ' ', m.group().strip()) 

pat = re.compile(r"^\w+\s+=\s\(\n.*?\n\)$", re.S | re.M) 
mdls_output = pat.sub(myfn, mdls_output) 
+0

I * sapevo * ci deve essere un modo per passare una funzione. Ho letto attraverso il 're' doc, ma la maggior parte ha perso questo. Grazie. – smargh

Problemi correlati