Ich habe einige Rohdaten wie folgt:
%Vor%Die Regel der Daten ist:
Nicht jeder beginnt mit "Dear", und wenn es welche gibt, muss es mit Kosten enden
Das Element kann nicht immer normale Wörter sein, es könnte ohne Grenzen geschrieben werden (einschließlich str, num, etc.)
Ich möchte die Informationen gruppieren und habe versucht, Regex zu verwenden. Das habe ich vorher versucht:
%Vor%Nun sieht die Ausgabe wie folgt aus:
%Vor% Ich zeige oben, was ich will. Wenn jedoch item
durch eine seltsame Zeichenfolge wie A1~A10
ersetzt wird, erhalten einige Ausgaben falsche Informationen:
Ich denke, das konstante Format in item field
ist, dass es immer mit ,
endet (falls es welche gibt). Aber ich weiß einfach nicht, wie ich den Vorteil nutzen soll.
Ich dachte, es ist vorübergehend erfolgreich, indem ich den obigen Code benutze. Ich dachte, dass (?P<item>\w+)
wie (?P<item>.+)
ersetzt werden muss. Wenn ich das tue, wird es eine falsche Zeichenfolge im Tupel nehmen wie:
Wie könnte ich die Daten in dem gewünschten Format lesen, indem ich die Regex in Python verwende?
Ich habe diesen regulären Ausdruck versucht
^(Dear)?\s*(?P<name>\w*)\D*(?P<num>\d+)\sof\s(?P<drink>\w*)(,\D*(?P<cost>\d+)\D*)?
Erklärung
^(Dear)?
Übereinstimmungslinie, die entweder mit Dear
if exists (?P<name>\w*)
Eine Namenserfassungsgruppe, um den Namen \D*
stimmt mit allen nicht einstelligen Zeichen (?P<num>\d+)
benannte Erfassungsgruppe, um die num
. \sof\s
übereinstimmende Zeichenfolge of
(?P<drink>\w*)
, um das Getränk zu bekommen (,\D*(?P<cost>\d+)\D*)?
Dies ist eine optionale Gruppe, um die Kosten für das Getränk zu erhalten mit
%Vor%Erster Datenausschnitt
%Vor%Zweites Datenschnipsel
%Vor%Ohne Regex:
%Vor% Es ist egal, welche Zeichen außer Leerzeichen verwendet werden, bis der Produktname, deshalb ist jede Zeile durch Leerzeichen in 5 Teile aufgeteilt. Wenn die Zeile mit "Dear" beginnt, wird der letzte Teil durch das Komma getrennt, um den Produktnamen und den Preis zu extrahieren. Beachten Sie, dass Sie, wenn sich der Preis immer an der gleichen Stelle befindet (dh nach "cost"), die innerste for-Schleife vermeiden und sie durch price = tmp[1].split()[1]
Hinweis: Wenn Sie verhindern möchten, dass leere Zeilen verarbeitet werden, können Sie die erste for -Schleife wie folgt ändern:
%Vor% Ich würde dieses regex
verwenden:
Demo
%Vor%Erläuterung
Der erste Abschnitt Ihrer Regex ist vollkommen in Ordnung, hier ist der knifflige Teil:
(?P<item>[^,]+)
Da wir sicher sind, dass die Zeichenfolge ein Komma enthält, wenn die Kosten Zeichenfolge vorhanden ist, sagen wir hier, dass wir alles andere als wollen Komma , um den Elementwert festzulegen.
(?:,\D+)?(?P<costs>\d+)?
Hier verwenden wir zwei Gruppen. Die wichtige Sache ist die ?
nach der Klammer , die die Gruppen einschließt:
'?' Bewirkt, dass der resultierende RE 0 oder 1 Wiederholungen des vorheriges RE. ab? passt entweder 'a' oder 'ab' an.
Also verwenden wir ?
, um beide Möglichkeiten (mit der cost Zeichenfolge vorhanden oder nicht)
(?:,\D+)
ist ein nicht erfassendes wird mit einem Komma gefolgt von allem außer einer Ziffer übereinstimmen.
(?P<costs>\d+)
erfasst jede Ziffer in der benannten Gruppe cost .
Wenn Sie .+
verwenden, greift das Untermuster den gesamten Rest der Zeile, da .
mit jedem Zeichen übereinstimmt, außer einem Zeilenumbruch ohne das re.S
-Flag.
Sie können \w+
durch ein negiertes Zeichenklassen-Untermuster [^,]+
ersetzen, um einem oder mehreren Zeichen außer einem Komma zu entsprechen:
Sehen Sie sich die IDEONE-Demo an:
%Vor%Ausgabe:
%Vor%