Antworten:
Ich habe Folgendes mit großem Erfolg verwendet:
(["'])(?:(?=(\\?))\2.)*?\1
Es unterstützt auch verschachtelte Anführungszeichen.
Für diejenigen, die eine ausführlichere Erklärung der Funktionsweise wünschen, finden Sie hier eine Erklärung von Benutzer Ephemient :
([""'])
ein Zitat abgleichen;((?=(\\?))\2.)
Wenn ein Backslash vorhanden ist, verschlingen Sie ihn und stimmen Sie einem Charakter zu, ob dies passiert oder nicht.*?
viele Male übereinstimmen (nicht gierig, um das Schlusszitat nicht zu essen);\1
stimmen mit dem gleichen Zitat überein, das zum Öffnen verwendet wurde.
"foo\"
. Der Look-Ahead-Trick macht den ?
Quantifizierer besitzergreifend (auch wenn der Regex-Geschmack die ?+
Syntax oder die atomare Gruppierung nicht unterstützt )
(["'])(?:\\.|[^\\])*?\1
Im Allgemeinen suchen Sie nach dem folgenden Fragment für reguläre Ausdrücke:
"(.*?)"
Dies nutzt die nicht gierigen *? Operator, um alles zu erfassen, bis auf das nächste doppelte Anführungszeichen. Anschließend verwenden Sie einen sprachspezifischen Mechanismus, um den übereinstimmenden Text zu extrahieren.
In Python können Sie Folgendes tun:
>>> import re
>>> string = '"Foo Bar" "Another Value"'
>>> print re.findall(r'"(.*?)"', string)
['Foo Bar', 'Another Value']
"hello \" world"
"(.*?(?<!\\))"
Ich würde gehen für:
"([^"]*)"
Das [^ "] ist ein regulärer Ausdruck für jedes Zeichen außer ' " '.
Der Grund , warum ich dies gegenüber dem nicht gierigen Operator "Viele" verwende, ist, dass ich das ständig nachschlagen muss, um sicherzugehen, dass ich es richtig verstehe.
Sehen wir uns zwei effiziente Möglichkeiten an, mit Escape-Anführungszeichen umzugehen. Diese Muster sind weder prägnant noch ästhetisch, sondern effizient.
Diese Methoden verwenden die Unterscheidung der ersten Zeichen, um schnell Anführungszeichen in der Zeichenfolge zu finden, ohne die Kosten einer Abwechslung. (Die Idee ist, Zeichen, die keine Anführungszeichen sind, schnell zu verwerfen, ohne die beiden Zweige der Abwechslung zu testen.)
Der Inhalt zwischen Anführungszeichen wird mit einer abgewickelten Schleife (anstelle eines wiederholten Wechsels) beschrieben, um auch effizienter zu sein: [^"\\]*(?:\\.[^"\\]*)*
Um mit Zeichenfolgen umzugehen, die keine ausgewogenen Anführungszeichen haben, können Sie stattdessen Possessivquantifizierer verwenden: [^"\\]*+(?:\\.[^"\\]*)*+
oder eine Problemumgehung, um sie zu emulieren und zu viel Backtracking zu verhindern. Sie können auch festlegen, dass ein Teil in Anführungszeichen ein Eröffnungszitat bis zum nächsten (nicht maskierten) Anführungszeichen oder dem Ende der Zeichenfolge sein kann. In diesem Fall müssen keine Possessivquantifizierer verwendet werden. Sie müssen nur das letzte Anführungszeichen optional machen.
Hinweis: Manchmal werden Anführungszeichen nicht mit einem Backslash maskiert, sondern durch Wiederholen des Anführungszeichens. In diesem Fall sieht das Inhaltsuntermuster folgendermaßen aus:[^"]*(?:""[^"]*)*
Die Muster vermeiden die Verwendung einer Erfassungsgruppe und einer Rückreferenz (ich meine so etwas wie (["']).....\1
) und verwenden eine einfache Abwechslung, jedoch mit ["']
dem Faktor am Anfang.
Perl wie:
["'](?:(?<=")[^"\\]*(?s:\\.[^"\\]*)*"|(?<=')[^'\\]*(?s:\\.[^'\\]*)*')
(Beachten Sie, dass dies (?s:...)
ein syntaktischer Zucker ist, um den Dotall / Singleline-Modus innerhalb der nicht erfassenden Gruppe einzuschalten. Wenn diese Syntax nicht unterstützt wird, können Sie diesen Modus für alle Muster einfach einschalten oder den Punkt durch ersetzen. [\s\S]
)
(Die Art und Weise, wie dieses Muster geschrieben wird, ist vollständig "handgesteuert" und berücksichtigt eventuelle motorinterne Optimierungen nicht.)
ECMA-Skript:
(?=["'])(?:"[^"\\]*(?:\\[\s\S][^"\\]*)*"|'[^'\\]*(?:\\[\s\S][^'\\]*)*')
POSIX erweitert:
"[^"\\]*(\\(.|\n)[^"\\]*)*"|'[^'\\]*(\\(.|\n)[^'\\]*)*'
oder einfach:
"([^"\\]|\\.|\\\n)*"|'([^'\\]|\\.|\\\n)*'
/pattern/
ohne sich etwas zu entziehen (anstelle der Objektnotation new RegExp("(?=[\"'])(?:\"[^\"\\\\]*...");
)
s
hier entfernen : (?s:
und wenn Sie (?s)
irgendwo in das Muster setzen.
Der RegEx der akzeptierten Antwort gibt die Werte einschließlich der umgebenden Anführungszeichen zurück: "Foo Bar"
und "Another Value"
als Übereinstimmungen.
Hier sind RegEx, die nur die Werte zwischen Anführungszeichen zurückgeben (wie vom Fragesteller verlangt):
Nur doppelte Anführungszeichen (Wert der Erfassungsgruppe 1 verwenden):
"(.*?[^\\])"
Nur einfache Anführungszeichen (Wert der Erfassungsgruppe 1 verwenden):
'(.*?[^\\])'
Beides (Wert der Erfassungsgruppe 2 verwenden):
(["'])(.*?[^\\])\1
- -
Alle Unterstützung entkam und verschachtelte Anführungszeichen.
src="(.*)"
aber offensichtlich hat es alles vor dem letzten ausgewählt ", Ihr REGEX hat jedoch nur den Inhalt von src =" "ausgewählt, aber ich habe nicht verstanden, wie?
Insbesondere erzeugt keine dieser Antworten einen regulären Ausdruck, bei dem die zurückgegebene Übereinstimmung der Text in den Anführungszeichen ist, nach dem gefragt wird. MA-Madden versucht es, bekommt aber nur das Insider-Match als gefangene Gruppe und nicht das ganze Match. Ein Weg, dies tatsächlich zu tun, wäre:
(?<=(["']\b))(?:(?=(\\?))\2.)*?(?=\1)
Beispiele hierfür finden Sie in dieser Demo unter https://regex101.com/r/Hbj8aP/1
Der Schlüssel hier ist das positive Aussehen am Anfang (das ?<=
) und das positive Aussehen am Ende (das ?=
). Das Lookbehind schaut hinter das aktuelle Zeichen, um nach einem Zitat zu suchen. Wenn es gefunden wird, beginnen Sie von dort aus, und der Lookahead überprüft das vorausschauende Zeichen auf ein Zitat. Wenn es gefunden wird, stoppen Sie dieses Zeichen. Die Lookbehind-Gruppe (the ["']
) wird in Klammern gesetzt, um eine Gruppe für das am Anfang gefundene Zitat zu erstellen. Diese wird dann am Ende des Lookaheads verwendet (?=\1)
, um sicherzustellen, dass sie nur stoppt, wenn das entsprechende Zitat gefunden wird.
Die einzige andere Komplikation besteht darin, dass der Lookahead das Endzitat nicht tatsächlich verbraucht und vom Start-Lookbehind wiedergefunden wird, wodurch der Text zwischen End- und Startzitaten in derselben Zeile übereinstimmt. Das Einfügen einer Wortgrenze in das Eröffnungszitat ( ["']\b
) hilft dabei, obwohl ich im Idealfall gerne am Lookahead vorbeikommen würde, aber ich denke nicht, dass dies möglich ist. Das Bit, das entkommene Zeichen in der Mitte zulässt, habe ich direkt aus Adams Antwort entnommen.
Das (["'])(?:(?=(\\?))\2.)*?\1
obige Muster macht den Job, aber ich bin besorgt über seine Leistungen (es ist nicht schlecht, könnte aber besser sein). Meins darunter ist ~ 20% schneller.
Das Muster "(.*?)"
ist nur unvollständig. Mein Rat für alle, die dies lesen, ist, ES NICHT ZU VERWENDEN !!!
Zum Beispiel kann es nicht viele Zeichenfolgen erfassen (bei Bedarf kann ich einen ausführlichen Testfall bereitstellen), wie den folgenden:
$ string = 'Wie geht es dir? Mir geht es
\'
gut, danke ';
Der Rest von ihnen ist genauso "gut" wie der oben.
Wenn Ihnen Leistung und Präzision wirklich am Herzen liegen, beginnen Sie mit dem folgenden:
/(['"])((\\\1|.)*?)\1/gm
In meinen Tests wurde jeder String abgedeckt, den ich getroffen habe. Wenn Sie jedoch etwas finden, das nicht funktioniert, würde ich es gerne für Sie aktualisieren.
Ich mochte Eugen Mihailescus Lösung , um den Inhalt zwischen Anführungszeichen abzugleichen und gleichzeitig Anführungszeichen zu vermeiden. Ich habe jedoch einige Probleme beim Entkommen entdeckt und mir den folgenden regulären Ausdruck ausgedacht, um sie zu beheben:
(['"])(?:(?!\1|\\).|\\.)*\1
Es macht den Trick und ist immer noch ziemlich einfach und leicht zu warten.
Demo (mit einigen weiteren Testfällen; Sie können sie gerne verwenden und erweitern).
PS: Wenn Sie nur den Inhalt zwischen Anführungszeichen in der vollständigen Übereinstimmung ( $0
) möchten und keine Angst vor der Leistungsstrafe haben, verwenden Sie:
(?<=(['"])\b)(?:(?!\1|\\).|\\.)*(?=\1)
Leider musste ich ohne die Anführungszeichen als Anker eine Begrenzung hinzufügen, \b
die mit Leerzeichen und Nicht-Wort-Begrenzungszeichen nach dem Startzitat nicht gut funktioniert.
Alternativ können Sie die ursprüngliche Version ändern, indem Sie einfach eine Gruppe$2
hinzufügen und das Zeichenfolgenformular extrahieren :
(['"])((?:(?!\1|\\).|\\.)*)\1
PPS: Wenn Sie sich ausschließlich auf Effizienz konzentrieren, entscheiden Sie sich für die Lösung von Casimir et Hippolyte . Das ist ein guter.
-
, wie in Längengradkoordinaten.
Diese Version
steuert das Backtracking
/(["'])((?:(?!\1)[^\\]|(?:\\\\)*\\[^\\])*)\1/
MEHR ANTWORTEN! Hier ist die Lösung, die ich verwendet habe
\"([^\"]*?icon[^\"]*?)\"
TLDR;
ersetzen Sie das Wort Symbol mit , was Sie suchen in den Zitaten und voila!
Dies funktioniert so, dass nach dem Schlüsselwort gesucht wird und es egal ist, was sich sonst noch zwischen den Anführungszeichen befindet. EG:
id="fb-icon"
id="icon-close"
id="large-icon-close"
Der Regex sucht nach einem Anführungszeichen, "
dann nach einer möglichen Buchstabengruppe, die "
erst gefunden wird, icon
und nach einer möglichen Buchstabengruppe, die es nicht ist "
, sucht er nach einem Abschluss"
name="value"
durch ersetzen, name={"value"}
da der reguläre Ausdruck dieser Antwort icon
/ value
als zweite Gruppe zurückgibt (im Gegensatz zur akzeptierten Antwort). Finden : =\"([^\"]*?[^\"]*?)\"
Ersetzen :={"$1"}
Ich mochte Axemans expansivere Version, hatte aber einige Probleme damit (sie passte zum Beispiel nicht zusammen
foo "string \\ string" bar
oder
foo "string1" bar "string2"
richtig, also habe ich versucht, es zu beheben:
# opening quote
(["'])
(
# repeat (non-greedy, so we don't span multiple strings)
(?:
# anything, except not the opening quote, and not
# a backslash, which are handled separately.
(?!\1)[^\\]
|
# consume any double backslash (unnecessary?)
(?:\\\\)*
|
# Allow backslash to escape characters
\\.
)*?
)
# same character as opening quote
\1
string = "\" foo bar\" \"loloo\""
print re.findall(r'"(.*?)"',string)
Probieren Sie es einfach aus, funktioniert wie ein Zauber !!!
\
zeigt das Sprungzeichen an
" foo bar" "loloo"
. Ich vermute, Sie wollten das in eine rohe Zeichenfolge einwickeln, wie Sie es mit dem regulären Ausdruck getan haben : r'"\" foo bar\" \"loloo\""'
. Bitte nutzen Sie die hervorragenden Formatierungsfunktionen von SO, wann immer dies angemessen ist. Es ist nicht nur Kosmetik; Wir können buchstäblich nicht sagen, was Sie sagen wollen, wenn Sie sie nicht verwenden. Und willkommen bei Stack Overflow !
echo 'junk "Foo Bar" not empty one "" this "but this" and this neither' | sed 's/[^\"]*\"\([^\"]*\)\"[^\"]*/>\1</g'
Dies führt zu:> Foo Bar <> <> aber dies <
Hier habe ich der Übersichtlichkeit halber die Ergebniszeichenfolge zwischen> <gezeigt, wobei wir auch die nicht gierige Version mit diesem sed-Befehl verwenden. Wir werfen zuerst den Müll davor und danach weg und ersetzen ihn dann durch den Teil zwischen den "". 's und umgeben dies mit> <' s.
Von Greg H. konnte ich diesen regulären Ausdruck erstellen, der meinen Bedürfnissen entspricht.
Ich musste einem bestimmten Wert entsprechen, der durch Anführungszeichen qualifiziert wurde. Es muss eine vollständige Übereinstimmung sein, keine teilweise Übereinstimmung sollte einen Treffer auslösen
zB "test" konnte nicht mit "test2" übereinstimmen.
reg = r"""(['"])(%s)\1"""
if re.search(reg%(needle), haystack, re.IGNORECASE):
print "winning..."
Jäger
Wenn Sie versuchen, Zeichenfolgen zu finden, die nur ein bestimmtes Suffix haben, z. B. die Punktsyntax, können Sie Folgendes versuchen:
\"([^\"]*?[^\"]*?)\".localized
Wo .localized
ist das Suffix?
Beispiel:
print("this is something I need to return".localized + "so is this".localized + "but this is not")
Es wird erfassen "this is something I need to return".localized
und "so is this".localized
aber nicht "but this is not"
.
Eine ergänzende Antwort für die Teilmenge der Microsoft VBA-Codierer verwendet nur einer die Bibliothek, Microsoft VBScript Regular Expressions 5.5
und dies ergibt den folgenden Code
Sub TestRegularExpression()
Dim oRE As VBScript_RegExp_55.RegExp '* Tools->References: Microsoft VBScript Regular Expressions 5.5
Set oRE = New VBScript_RegExp_55.RegExp
oRE.Pattern = """([^""]*)"""
oRE.Global = True
Dim sTest As String
sTest = """Foo Bar"" ""Another Value"" something else"
Debug.Assert oRE.test(sTest)
Dim oMatchCol As VBScript_RegExp_55.MatchCollection
Set oMatchCol = oRE.Execute(sTest)
Debug.Assert oMatchCol.Count = 2
Dim oMatch As Match
For Each oMatch In oMatchCol
Debug.Print oMatch.SubMatches(0)
Next oMatch
End Sub
Für mich hat das funktioniert:
|([\'"])(.*?)\1|i
Ich habe in einem Satz wie diesem verwendet:
preg_match_all('|([\'"])(.*?)\1|i', $cont, $matches);
und es hat super funktioniert.
Alle obigen Antworten sind gut ... außer dass sie NICHT alle Unicode-Zeichen unterstützen! bei ECMA Script (Javascript)
Wenn Sie ein Knotenbenutzer sind, möchten Sie möglicherweise die geänderte Version der akzeptierten Antwort, die alle Unicode-Zeichen unterstützt:
/(?<=((?<=[\s,.:;"']|^)["']))(?:(?=(\\?))\2.)*?(?=\1)/gmu
Versuchen Sie es hier .
? The preceding token is not quantifiable