Mein regulärer Ausdruck stimmt zu sehr überein.Wie sorge ich dafür, dass es aufhört?

StackOverflow https://stackoverflow.com/questions/22444

  •  09-06-2019
  •  | 
  •  

Frage

J0000000: Transaction A0001401 started on 8/22/2008 9:49:29 AM
J0000010: Project name: E:\foo.pf
J0000011: Job name: MBiek Direct Mail Test
J0000020: Document 1 - Completed successfully

Ich habe diesen riesigen, hässlichen String und versuche, mithilfe von Regex Teile daraus zu extrahieren.

In diesem Fall möchte ich alles nach „Projektname“ erfassen, bis zu dem Teil, wo „J0000011:“ steht (die 11 wird jedes Mal eine andere Nummer sein).

Hier ist der reguläre Ausdruck, mit dem ich gespielt habe

Project name:\s+(.*)\s+J[0-9]{7}:

Das Problem ist, dass es nicht aufhört, bis es das Ziel erreicht J0000020: Am Ende.

Wie kann ich dafür sorgen, dass die Regex beim ersten Auftreten von stoppt? J[0-9]{7}?

War es hilfreich?

Lösung

Machen .* nicht gierig durch Hinzufügen von '?' Danach:

Project name:\s+(.*?)\s+J[0-9]{7}:

Andere Tipps

Die Verwendung nicht gieriger Quantoren ist hier wahrscheinlich die beste Lösung, auch weil sie effizienter ist als die gierige Alternative:Greedy-Matches gehen im Allgemeinen so weit wie möglich (hier bis zum Ende des Textes!) und verfolgen dann Zeichen für Zeichen zurück, um zu versuchen, den darauffolgenden Teil abzugleichen.

Erwägen Sie jedoch stattdessen die Verwendung einer negativen Zeichenklasse:

Project name:\s+(\S*)\s+J[0-9]{7}:

\S bedeutet „alles außer einem Leerzeichen und das ist genau das, was Sie wollen.“

Also, ".*" ist ein gieriger Selektor.Sie machen es nicht gierig, indem Sie es verwenden ".*?" Bei Verwendung des letztgenannten Konstrukts gleicht die Regex-Engine bei jedem Schritt den Text mit dem ab "." Versuchen Sie, mit der Marke übereinzustimmen, die nach dem kommt ".*?".Das heißt, wenn zum Beispiel nach dem nichts mehr kommt ".*?", dann passt es zu nichts.

Hier ist, was ich verwendet habe. s enthält Ihre Originalzeichenfolge.Dieser Code ist .NET-spezifisch, aber die meisten Regex-Varianten haben etwas Ähnliches.

string m = Regex.Match(s, @"Project name: (?<name>.*?) J\d+").Groups["name"].Value;

Ich würde Ihnen auch empfehlen, mit „Expresso“ mit regulären Ausdrücken zu experimentieren – es ist ein großartiges (und kostenloses) Dienstprogramm zum Bearbeiten und Testen von Regex.

Einer der Vorteile besteht darin, dass die Benutzeroberfläche viele Regex-Funktionen bietet, mit denen Regex-Unerfahrene möglicherweise nicht vertraut sind, sodass sie diese neuen Konzepte leicht erlernen können.

Wenn Sie beispielsweise Ihren regulären Ausdruck über die Benutzeroberfläche erstellen und „*“ auswählen, haben Sie die Möglichkeit, das Kontrollkästchen „So wenige wie möglich“ zu aktivieren und den resultierenden regulären Ausdruck anzuzeigen sowie sein Verhalten zu testen, auch wenn Sie damit nicht vertraut sind nicht gierige Ausdrücke vor.

Auf ihrer Website zum Download verfügbar:http://www.ultrapico.com/Expresso.htm

Express-Download:http://www.ultrapico.com/ExpressoDownload.htm

(Projektname:\s+[A-Z]:(?:\\w+)+.[a-zA-Z]+\s+J[0-9]{7})(?=:)

Das wird für Sie funktionieren.

Das Hinzufügen von (?:\\w+)+.[a-zA-Z]+ ist restriktiver anstelle von .*

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top