Ich habe ein bisschen Probleme damit, dass ein Python-Regex funktioniert, wenn er mit Text verglichen wird, der mehrere Zeilen umfasst. Der Beispieltext lautet ('\ n' ist eine neue Zeile)
some Varying TEXT\n
\n
DSJFKDAFJKDAFJDSAKFJADSFLKDLAFKDSAF\n
[more of the above, ending with a newline]\n
[yep, there is a variable number of lines here]\n
\n
(repeat the above a few hundred times).
Ich möchte zwei Dinge erfassen: den Teil 'some_Varying_TEXT' und alle Zeilen in Großbuchstaben, die in einer Erfassung zwei Zeilen darunter stehen (ich kann die Zeilenumbrüche später entfernen). Ich habe es mit ein paar Ansätzen versucht:
re.compile(r"^>(\w+)$$([.$]+)^$", re.MULTILINE) # try to capture both parts
re.compile(r"(^[^>][\w\s]+)$", re.MULTILINE|re.DOTALL) # just textlines
und viele Variationen davon ohne Glück. Der letzte scheint nacheinander mit den Textzeilen übereinzustimmen, was ich nicht wirklich will. Ich kann den ersten Teil abfangen, kein Problem, aber ich kann die 4-5 Zeilen Großbuchstaben nicht abfangen. Ich möchte, dass match.group (1) some_Varying_Text und group (2) line1 + line2 + line3 + usw. ist, bis die leere Zeile gefunden wird.
Wenn jemand neugierig ist, soll es sich um eine Sequenz von Aminosäuren handeln, aus denen ein Protein besteht.
>
Charakter. Sollte es?Antworten:
Versuche dies:
Ich denke, Ihr größtes Problem ist, dass Sie erwarten, dass die
^
und$
Anker mit den Zeilenvorschüben übereinstimmen, aber das tun sie nicht. Entspricht im mehrzeiligen Modus^
der Position unmittelbar nach einer neuen Zeile und$
der Position unmittelbar vor einer neuen Zeile.Beachten Sie auch, dass eine neue Zeile aus einem Zeilenvorschub (\ n), einem Wagenrücklauf (\ r) oder einem Wagenrücklauf + Zeilenvorschub (\ r \ n) bestehen kann. Wenn Sie nicht sicher sind, ob Ihr Zieltext nur Zeilenvorschübe verwendet, sollten Sie diese umfassendere Version des regulären Ausdrucks verwenden:
Übrigens möchten Sie den DOTALL-Modifikator hier nicht verwenden. Sie verlassen sich auf die Tatsache, dass der Punkt mit allen Zeilen außer Zeilenumbrüchen übereinstimmt.
quelle
Das wird funktionieren:
Einige Erklärungen zu diesem regulären Ausdruck könnten nützlich sein:
^(.+?)\n\n((?:[A-Z]+\n)+)
^
) bedeutet "am Zeilenanfang beginnen". Beachten Sie, dass es nicht mit der Newline selbst übereinstimmt (dasselbe gilt für $: Es bedeutet "kurz vor einer Newline", aber es stimmt nicht mit der Newline selbst überein).(.+?)\n\n
Bedeutet dann "so wenig Zeichen wie möglich abgleichen (alle Zeichen sind zulässig), bis Sie zwei Zeilenumbrüche erreichen". Das Ergebnis (ohne die Zeilenumbrüche) wird in die erste Gruppe eingefügt.[A-Z]+\n
bedeutet "Ordne so viele Großbuchstaben wie möglich zu, bis du eine neue Zeile erreichst. Dies definiert, was ich eine Textzeile nennen werde .((?:
Textzeile)+)
bedeutet, dass eine oder mehrere Textzeilen übereinstimmen, aber nicht jede Zeile einer Gruppe zugeordnet wird. Stattdessen setzen alle die Textzeilen in einer Gruppe.\n
dem regulären Ausdruck ein Finale hinzufügen, wenn Sie am Ende einen doppelten Zeilenumbruch erzwingen möchten.\n
oder\r
oder\r\n
), korrigieren Sie einfach den regulären Ausdruck, indem Sie jedes Vorkommen von\n
by ersetzen(?:\n|\r\n?)
.quelle
Wenn jede Datei nur eine Sequenz von Aminosäuren enthält, würde ich überhaupt keine regulären Ausdrücke verwenden. Nur so etwas:
quelle
finden:
\ 1 = etwas variierender Text
\ 2 = Zeilen aller CAPS
Bearbeiten (Beweis, dass dies funktioniert):
quelle
Das Folgende ist ein regulärer Ausdruck, der einem mehrzeiligen Textblock entspricht:
quelle
Meine Vorliebe.
Zu diesem Zeitpunkt haben Sie someVaryingText als Zeichenfolge und die Säuren als Liste von Zeichenfolgen. Sie können
"".join( acids )
eine einzelne Zeichenfolge erstellen.Ich finde das weniger frustrierend (und flexibler) als mehrzeilige Regexe.
quelle