Dies ist eines der schwierigsten Dinge, die ich je versucht habe. Im Laufe der Jahre habe ich gesucht, aber ich kann einfach keinen Weg finden, dies zu tun - passe eine Zeichenkette an, die nicht von einem gegebenen Zeichen umgeben ist, wie Anführungszeichen oder größere / weniger als Symbole.
Eine solche Regex könnte URLs entsprechen, die nicht in HTML-Links enthalten sind, SQL-Tabellen.Spaltenwerte nicht in Anführungszeichen und viele andere Dinge.
%Vor%Wie passt man eine Zeichenkette (THIS) an, wenn sie nicht von einem gegebenen Zeichen umgeben ist?
%Vor%Hier ist ein Testmuster: Ein Regex wie das, woran ich denke, würde nur dem ersten "Zitat" entsprechen.
Um zu zitieren: "Zitiere mich nicht, damit ich dich nicht zitiere!"
Die beste Lösung hängt davon ab, was Sie über die Eingabe wissen. Wenn Sie beispielsweise nach Dingen suchen, die nicht in doppelte Anführungszeichen eingeschlossen sind, bedeutet das, dass doppelte Anführungszeichen immer richtig ausbalanciert sind? Können sie mit umgekehrten Schrägstrichen oder in einfache Anführungszeichen eingeschlossen werden?
Unter der Annahme des einfachsten Falles - keine Verschachtelung, keine Flucht - könnten Sie ein Lookahead wie folgt verwenden:
%Vor%Nach dem Auffinden des Ziels (THIS) zählt der Lookahead grundsätzlich die doppelten Anführungszeichen nach diesem Punkt bis zum Ende der Zeichenkette. Wenn es eine ungerade Anzahl von ihnen gibt, muss die Übereinstimmung innerhalb eines Paares von doppelten Anführungszeichen aufgetreten sein, so dass sie nicht gültig ist (das Lookahead schlägt fehl).
Wie Sie herausgefunden haben, ist dieses Problem nicht gut für reguläre Ausdrücke geeignet. Aus diesem Grund hängen alle vorgeschlagenen Lösungen von Funktionen ab, die in regulären echten regulären Ausdrücken nicht enthalten sind, wie das Erfassen von Gruppen, Lookarounds, widerwilligen und besitzergreifenden Quantifizierern. Ich würde es nicht einmal versuchen ohne Possessiv-Quantoren oder atomic groups .
EDIT: Um diese Lösung zu erweitern, um doppelte Anführungszeichen zu berücksichtigen, die mit Backslashes maskiert werden können, müssen Sie nur die Teile der Regex ersetzen, die "alles, was kein Anführungszeichen ist" entsprechen:
%Vor%mit "alles was kein Zitat oder ein umgekehrter Schrägstrich ist, oder ein Backslash gefolgt von irgendetwas":
%Vor%Da Backslash-Escape-Sequenzen relativ selten sind, ist es sinnvoll, so viele nicht-deklarierte Zeichen wie möglich zu finden, während Sie sich in diesem Teil der Regex befinden:
%Vor%Wenn Sie alles zusammensetzen, wird die Regex:
%Vor%Auf Ihre Testzeichenfolge angewendet:
%Vor% ... sollte mit 'THIS1'
, 'THIS3'
, 'THIS4'
und 'THIS6'
übereinstimmen.
Es ist ein bisschen schwierig. Es gibt Möglichkeiten, solange Sie die Verschachtelung nicht im Auge behalten müssen. Zum Beispiel vermeiden wir Zitat-Sachen:
%Vor%Oder erklären:
%Vor%Nun gibt es andere Möglichkeiten, dies zu tun, aber vielleicht nicht so flexibel. Zum Beispiel, wenn Sie DIESE finden möchten, solange es keine vorangehende "//" oder "#" Sequenz gab - mit anderen Worten, ein THIS außerhalb eines Kommentars, könnten Sie es so machen:
%Vor% Hier ist (?<!...)
ein negativer Look-Behind. Es wird nicht mit diesen Zeichen übereinstimmen, aber es wird getestet, dass sie nicht vor DIESEM angezeigt werden.
Wie für beliebig beliebig verschachtelte Strukturen - zum Beispiel n (
geschlossen bis n )
- können sie nicht durch reguläre Ausdrücke dargestellt werden. Perl kann es tun, aber es ist kein regulärer Ausdruck.
Nun, reguläre Ausdrücke sind einfach das falsche Werkzeug dafür, also ist es ganz natürlich, dass es schwer ist.
Dinge, die von anderen Dingen umgeben sind, sind keine gültigen Regeln für reguläre Grammatiken. Die meisten (man könnte vielleicht sagen, alle ernsthaften) Markup- und Programmiersprachen sind nicht regelmäßig. Solange es keine Verschachtelung gibt, können Sie möglicherweise einen Parser mit einer Regex simulieren, aber vergewissern Sie sich, dass Sie verstehen, was Sie tun.
Für HTML / XML verwenden Sie einfach einen HTML- bzw. XML-Parser; Diese gibt es für fast jede Sprache oder jedes Web-Framework. die Verwendung von ihnen beinhaltet typischerweise nur ein paar Zeilen Code. Bei Tabellen können Sie möglicherweise einen CSV-Parser verwenden oder bei Bedarf Ihren eigenen Parser rollen, der die Teile innerhalb / außerhalb von Anführungszeichen extrahiert. Nach dem Extrahieren der Teile, an denen Sie interessiert sind, können Sie einen einfachen Stringvergleich oder reguläre Ausdrücke verwenden, um Ihre Ergebnisse zu erhalten.
Nachdem wir über das Verschachteln von Elementen ("a" dieses und "dieses" ") und rückgestrichener Elemente" \ "nachgedacht haben, scheint es wirklich wahr zu sein, dass dies kein Auftrag für Regex ist. Allerdings das einzige Was ich mir vorstellen kann, um dieses Problem zu lösen, wäre ein Regex-ähnlicher Char-by-Char-Parser, der $ quote_level = ### markiert, wenn er ein gültiges Zitat oder Unterangebot findet und eingibt die Zeichenfolge, die Sie wissen würden, ob Sie in einem bestimmten Zeichen waren, auch wenn es durch einen Schrägstrich oder was auch immer entkommt.
Ich denke, mit einem Char-by-Char-Parser wie diesem könnten Sie die String-Position von Start- / End-Anführungszeichen markieren, so dass Sie die Zeichenfolge nach Anführungszeichen segmentieren und nur außerhalb der Anführungszeichen verarbeiten können.
Hier ist ein Beispiel, wie dieser Parser intelligent genug sein müsste, um verschachtelte Ebenen zu handhaben.
%Vor%Wie Alan M sagte, können Sie regex verwenden, um nach einer ungeraden Zahl zu suchen, um Sie über Ihre Position innerhalb oder außerhalb einer gegebenen Zeichenkette zu informieren. Wenn wir das Zitatbeispiel nehmen, scheinen wir einer Lösung für dieses Problem sehr nahe zu sein. Das einzige, was übrig bleibt, ist die Handhabung von Ausflügen. (Ich bin sicher, dass verschachtelte Zitate fast unmöglich sind).
%Vor%Tags und Links regex