Wie erhalte ich den Teilstring " It's big \"problem "
mit einem regulären Ausdruck?
s = ' function(){ return " It\'s big \"problem "; }';
Wie erhalte ich den Teilstring " It's big \"problem "
mit einem regulären Ausdruck?
s = ' function(){ return " It\'s big \"problem "; }';
Antworten:
/"(?:[^"\\]|\\.)*"/
Arbeitet in The Regex Coach und PCRE Workbench.
Testbeispiel in JavaScript:
var s = ' function(){ return " Is big \\"problem\\", \\no? "; }';
var m = s.match(/"(?:[^"\\]|\\.)*"/);
if (m != null)
alert(m);
(?:...)
ist eine passive oder nicht erfassende Gruppe. Dies bedeutet, dass es später nicht mehr referenziert werden kann.
/(["'])(?:[^\1\\]|\\.)*?\1/
var s = ' my \\"new\\" string and \"this should be matched\"';
führt dieser Ansatz zu unerwarteten Ergebnissen.
Dieser stammt von nanorc.sample, das in vielen Linux-Distributionen erhältlich ist. Es wird zur Syntaxhervorhebung von Zeichenfolgen im C-Stil verwendet
\"(\\.|[^\"])*\"
var s = ' my \\"new\\" string and \"this should be matched\"';
führt dieser Ansatz zu unerwarteten Ergebnissen.
" \"(\\\\.|[^\\\"])*\" "
Wie von ePharaoh bereitgestellt, lautet die Antwort
/"([^"\\]*(\\.[^"\\]*)*)"/
Verwenden Sie diese Option, damit die oben genannten Zeichenfolgen entweder auf einfache oder doppelte Anführungszeichen angewendet werden
/"([^"\\]*(\\.[^"\\]*)*)"|\'([^\'\\]*(\\.[^\'\\]*)*)\'/
Die meisten der hier bereitgestellten Lösungen verwenden alternative Wiederholungspfade, dh (A | B) *.
Bei großen Eingaben können Stapelüberläufe auftreten, da einige Pattern-Compiler dies mithilfe der Rekursion implementieren.
Java zum Beispiel: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6337993
So etwas wie das:
"(?:[^"\\]*(?:\\.)?)*"
oder das von Guy Bedford bereitgestellte reduziert die Anzahl der Analyseschritte, wodurch die meisten Stapelüberläufe vermieden werden.
"(?:\\"|.)*?"
Durch das Abwechseln von \"
und die .
Übergänge über maskierte Anführungszeichen wird *?
sichergestellt, dass Sie nicht über das Ende der Zeichenfolge in Anführungszeichen hinausgehen. Funktioniert mit .NET Framework RE-Klassen
"\\"
/"(?:(?:\\"|[^"])*)"/g
Dies sollte
/"(?:[^"\\]++|\\.)*+"/
Entnommen direkt von man perlre
einem Linux-System mit installiertem Perl 5.22.0. Als Optimierung verwendet dieser reguläre Ausdruck die "positive" Form von beiden +
und *
um ein Zurückverfolgen zu verhindern, da vorher bekannt ist, dass eine Zeichenfolge ohne abschließendes Anführungszeichen auf keinen Fall übereinstimmen würde.
/(["\']).*?(?<!\\)(\\\\)*\1/is
sollte mit jeder Zeichenfolge in Anführungszeichen funktionieren
Dieser funktioniert perfekt auf PCRE und fällt nicht mit StackOverflow.
"(.*?[^\\])??((\\\\)+)?+"
Erläuterung:
"
;.*?
{Lazy match}; endet mit einem Nicht-Flucht-Charakter [^\\]
;(.*?[^\\])??
"
), es kann jedoch eine gerade Anzahl von Escape-Zeichenpaaren vorangestellt werden (\\\\)+
. und es ist Greedy (!) optional: ((\\\\)+)?+
{Greedy Matching}, weil die Zeichenfolge leer sein kann oder ohne Endpaare!"(.*?[^\\])?(\\\\)*"
Hier ist eine, die sowohl mit "als auch mit" funktioniert, und Sie können am Anfang ganz einfach andere hinzufügen.
("| ') (?: \\\ 1 | [^ \ 1]) *? \ 1
Es verwendet die Rückreferenz (\ 1), die genau mit der ersten Gruppe ("oder ') übereinstimmt.
[^\1]
sollte aber durch eine ersetzt werden, .
da es keine Anti-Back-Referenz gibt und es sowieso keine Rolle spielt. Die erste Bedingung wird immer übereinstimmen, bevor etwas Schlimmes passieren kann.
[^\1]
mit .
würde effektiv diese Regex ändern ("|').*?\1
und dann würde es passen "foo\"
in "foo \" bar"
. Das heißt, es [^\1]
ist schwer, tatsächlich zur Arbeit zu kommen. @ Mathiashansen - Sie sind besser dran mit dem unhandlichen und teuren (?!\1).
(so wäre der gesamte Regex mit einer gewissen Effizienzbereinigung (["'])(?:\\.|(?!\1).)*+\1
. Das +
ist optional, wenn Ihr Motor es nicht unterstützt.
Eine Option, die zuvor noch nicht angesprochen wurde, ist:
Dies hat den zusätzlichen Vorteil, dass es möglich ist, entkommene offene Tags korrekt abzugleichen.
Nehmen wir an, Sie hatten die folgende Zeichenfolge. String \"this "should" NOT match\" and "this \"should\" match"
Hier \"this "should" NOT match\"
sollte nicht abgestimmt werden und "should"
sollte sein. Darüber hinaus this \"should\" match
sollte abgestimmt werden und \"should\"
sollte nicht.
Zuerst ein Beispiel.
// The input string.
const myString = 'String \\"this "should" NOT match\\" and "this \\"should\\" match"';
// The RegExp.
const regExp = new RegExp(
// Match close
'([\'"])(?!(?:[\\\\]{2})*[\\\\](?![\\\\]))' +
'((?:' +
// Match escaped close quote
'(?:\\1(?=(?:[\\\\]{2})*[\\\\](?![\\\\])))|' +
// Match everything thats not the close quote
'(?:(?!\\1).)' +
'){0,})' +
// Match open
'(\\1)(?!(?:[\\\\]{2})*[\\\\](?![\\\\]))',
'g'
);
// Reverse the matched strings.
matches = myString
// Reverse the string.
.split('').reverse().join('')
// '"hctam "\dluohs"\ siht" dna "\hctam TON "dluohs" siht"\ gnirtS'
// Match the quoted
.match(regExp)
// ['"hctam "\dluohs"\ siht"', '"dluohs"']
// Reverse the matches
.map(x => x.split('').reverse().join(''))
// ['"this \"should\" match"', '"should"']
// Re order the matches
.reverse();
// ['"should"', '"this \"should\" match"']
Okay, jetzt um die RegExp zu erklären. Dies ist der reguläre Ausdruck, der leicht in drei Teile zerlegt werden kann. Wie folgt:
# Part 1
(['"]) # Match a closing quotation mark " or '
(?! # As long as it's not followed by
(?:[\\]{2})* # A pair of escape characters
[\\] # and a single escape
(?![\\]) # As long as that's not followed by an escape
)
# Part 2
((?: # Match inside the quotes
(?: # Match option 1:
\1 # Match the closing quote
(?= # As long as it's followed by
(?:\\\\)* # A pair of escape characters
\\ #
(?![\\]) # As long as that's not followed by an escape
) # and a single escape
)| # OR
(?: # Match option 2:
(?!\1). # Any character that isn't the closing quote
)
)*) # Match the group 0 or more times
# Part 3
(\1) # Match an open quotation mark that is the same as the closing one
(?! # As long as it's not followed by
(?:[\\]{2})* # A pair of escape characters
[\\] # and a single escape
(?![\\]) # As long as that's not followed by an escape
)
Dies ist in Bildform wahrscheinlich viel klarer: Erstellt mit Jex Regulex
Bild auf Github (JavaScript Regular Expression Visualizer). Entschuldigung, ich habe nicht den Ruf, Bilder aufzunehmen, daher ist es vorerst nur ein Link.
Hier ist eine Zusammenfassung einer Beispielfunktion, die dieses etwas fortgeschrittenere Konzept verwendet: https://gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js
Man muss bedenken, dass Regexps keine Silberkugel für alles sind, was man braucht. Einige Dinge sind einfacher mit einem Cursor und linearen, manuellen Suchen zu tun. Eine CFL würde den Trick ziemlich trivial machen, aber es gibt nicht viele CFL-Implementierungen (afaik).
Eine umfangreichere Version von https://stackoverflow.com/a/10786066/1794894
/"([^"\\]{50,}(\\.[^"\\]*)*)"|\'[^\'\\]{50,}(\\.[^\'\\]*)*\'|“[^”\\]{50,}(\\.[^“\\]*)*”/
Diese Version enthält auch
“
und Schließen ”
)Bei Regexpal herumgespielt und am Ende diesen Regex erhalten: (Frag mich nicht, wie es funktioniert, ich verstehe kaum, obwohl ich es geschrieben habe lol)
"(([^"\\]?(\\\\)?)|(\\")+)+"
Wenn es von Anfang an gesucht wird, kann das vielleicht funktionieren?
\"((\\\")|[^\\])*\"
Ich hatte ein ähnliches Problem beim Versuch, Zeichenfolgen in Anführungszeichen zu entfernen, die das Parsen einiger Dateien beeinträchtigen könnten.
Am Ende hatte ich eine zweistufige Lösung, die jeden verschlungenen regulären Ausdruck übertrifft, den Sie sich vorstellen können:
line = line.replace("\\\"","\'"); // Replace escaped quotes with something easier to handle
line = line.replaceAll("\"([^\"]*)\"","\"x\""); // Simple is beautiful
Einfacher zu lesen und wahrscheinlich effizienter.
Wenn Ihre IDE IntelliJ Idea ist, können Sie all diese Kopfschmerzen vergessen und Ihren regulären Ausdruck in einer String-Variablen speichern. Wenn Sie ihn kopieren und in das doppelte Anführungszeichen einfügen, ändert er sich automatisch in ein für den regulären Ausdruck akzeptables Format.
Beispiel in Java:
String s = "\"en_usa\":[^\\,\\}]+";
Jetzt können Sie diese Variable in Ihrem regulären Ausdruck oder überall verwenden.