2015-07-10 8 views
5

Ich versuche, Ausgabe von OS X mdls Befehl zu analysieren. Für einige Schlüssel ist der Wert eine Liste von Werten. Ich muss diese Schlüsselpaare korrekt erfassen. Alle Wertelisten beginnen mit einem ( und enden dann mit einem ).Effizient ersetzen mehrzeilige Liste Strings mit single_line Liste Zeichenfolge

Ich muss in der Lage sein, über alle Schlüssel, Wert-Paare zu iterieren, so dass ich mehrere Ausgänge richtig analysieren kann (dh mdls laufen auf mehrere Dateien, um eine einzige Ausgabe zu erzeugen, wo es keinen Unterschied gibt wo die Metadaten einer Datei enden und der andere beginnt. Ich habe unten einen Beispielcode.

Gibt es einen effizienteren Weg, dies zu tun?

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

Funktioniert Ihre Lösung? Sind Sie auf der Suche nach einer speichereffizienten Alternative oder einer Lösung, die * schneller * ist? – wwii

+0

Es funktioniert, aber es fühlt sich unnötig komplex an. Ich will * zwei 'n' verschachteln, aber ich konnte das nicht zur Arbeit bringen; das heißt, ersetze die mehrzeilige Liste für eine einzeilige Liste, die eine Normierung des Leerraums erfordern würde (z. B. re (r "^ \ w + \ s + = \ s \ (\ n. *? \ n \) $" , re (r '\ s +', '', '\ 1'.strip(), mdls_output) ') – smargh

+0

Es sieht meistens gut aus, aber deine Hauptregex ist ein bisschen falsch. Wahrscheinlich sollte' '^ \ w + \ s * = \ s * \ (\ n. *? \ n \) $ "'. Sollte das nicht 'mdls_output = mdls_output.replace (mdls_list [i], single_line_lists [i])'? – sln

Antwort

2

Sie können regex Ersatz Vorteil Pythons nehmen die eine Funktion als Ersatz-String nehmen. Die Funktion wird für jede Übereinstimmung mit dem Übereinstimmungsobjekt aufgerufen. Die zurückgegebene Zeichenfolge ersetzt die Übereinstimmung.

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

Ich wusste, dass es eine Möglichkeit geben muss, eine Funktion zu übergeben, ich lese durch das 're' Docs, aber die meisten haben das verpasst. – smargh

Verwandte Themen