Zum Beispiel diese Regex
(.*)<FooBar>
Wird zusammenpassen:
abcde<FooBar>
Aber wie kann ich erreichen, dass es über mehrere Zeilen hinweg übereinstimmt?
abcde
fghij<FooBar>
Zum Beispiel diese Regex
(.*)<FooBar>
Wird zusammenpassen:
abcde<FooBar>
Aber wie kann ich erreichen, dass es über mehrere Zeilen hinweg übereinstimmt?
abcde
fghij<FooBar>
Antworten:
Dies hängt von der Sprache ab, es sollte jedoch einen Modifikator geben, den Sie dem Regex-Muster hinzufügen können. In PHP ist es:
/(.*)<FooBar>/s
Das s am Ende bewirkt, dass der Punkt mit allen Zeichen einschließlich Zeilenumbrüchen übereinstimmt.
s
Modifikator nicht. Führen Sie stattdessen [^]*
den gleichen Effekt aus.
m
Modifikator
Versuche dies:
((.|\n)*)<FooBar>
Grundsätzlich heißt es "jedes Zeichen oder eine neue Zeile" und wird null oder mehrmals wiederholt.
((.|\n|\r)*)<FooBar>
[\s\S]*
oder (?s).*
.
Die Frage ist, kann das .
Muster mit jedem Zeichen übereinstimmen ? Die Antwort variiert von Motor zu Motor. Der Hauptunterschied besteht darin, ob das Muster von einer POSIX- oder einer Nicht-POSIX-Regex-Bibliothek verwendet wird.
Besonderer Hinweis zu Lua-Muster: Sie werden nicht als reguläre Ausdrücke betrachtet, .
stimmen jedoch mit allen Zeichen überein, genau wie POSIX-basierte Engines.
Noch ein Hinweis zu Matlab und Oktave: Das .
entspricht standardmäßig jedem Zeichen ( Demo ): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');
( tokens
enthält ein abcde\n fghij
Element).
Auch in allen BoostBei den Regex-Grammatiken stimmt der Punkt standardmäßig mit Zeilenumbrüchen überein. Mit der ECMAScript-Grammatik von Boost können Sie dies mit regex_constants::no_mod_m
( Quelle ) deaktivieren .
Wie für Orakel(es basiert auf POSIX), verwenden Sie die n
Option ( Demo ):select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual
POSIX-basierte Engines :
Ein bloßes entspricht .
bereits Zeilenumbrüchen, es müssen keine Modifikatoren verwendet werden, sieheBash( Demo ).
Das tcl( Demo ),postgresql( Demo ),r(TRE, Basis-R-Standard-Engine mit Nein perl=TRUE
, für Basis-R mit perl=TRUE
oder für Stringr / Stringi- Muster verwenden Sie den (?s)
Inline-Modifikator.) ( Demo ) Behandeln Sie dies ebenfalls auf .
die gleiche Weise.
Die meisten POSIX-basierten Tools verarbeiten Eingaben jedoch zeilenweise. Entspricht .
daher nicht den Zeilenumbrüchen, nur weil sie nicht im Geltungsbereich liegen. Hier einige Beispiele, wie Sie dies überschreiben können:
sed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/'
( H;1h;$!d;x;
schlürft die Datei in den Speicher). Wenn ganze Zeilen enthalten sein müssen sed '/start_pattern/,/end_pattern/d' file
(das Entfernen vom Anfang endet mit übereinstimmenden Zeilen) oder sed '/start_pattern/,/end_pattern/{{//!d;};}' file
(ohne übereinstimmende übereinstimmende Zeilen) kann berücksichtigt werden.perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str"
( -0
schlürft die gesamte Datei in den Speicher, -p
druckt die Datei nach Anwendung des von -e
). Beachten Sie, dass bei Verwendung -000pe
die Datei verschluckt \n\n
und der Absatzmodus aktiviert wird, in dem Perl aufeinanderfolgende Zeilenumbrüche ( ) als Datensatztrennzeichen verwendet.grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file
. Aktiviert hier z
das Schlürfen von Dateien, (?s)
aktiviert den DOTALL-Modus für das .
Muster, aktiviert den Modus ohne Berücksichtigung der (?i)
Groß- und Kleinschreibung, \K
lässt den bisher übereinstimmenden Text weg, *?
ist ein fauler Quantifizierer, (?=<Foobar>)
stimmt mit dem vorherigen Speicherort überein <Foobar>
.pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file
( M
aktiviert hier das Schlürfen von Dateien). Hinweis pcregrep
ist eine gute Lösung für Mac OS- grep
Benutzer.Nicht POSIX-basierte Engines :
s
Modifikator PCRE_DOTALL Modifikator : preg_match('~(.*)<Foobar>~s', $s, $m)
( Demo )RegexOptions.Singleline
Flag ( Demo ) verwenden: var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;
var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;
(?s)
Inline-Option verwenden:$s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]
s
Modifikator (oder die (?s)
Inline-Version zu Beginn) ( Demo ):/(.*)<FooBar>/s
re.DOTALL
(oder re.S
) Fahnen oder (?s)
Inline - Modifikator ( Demo ): m = re.search(r"(.*)<FooBar>", s, flags=re.S)
(und dann if m:
, print(m.group(1))
)Pattern.DOTALL
Modifikator (oder das Inline- (?s)
Flag) ( Demo ):Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
(?s)
In-Pattern-Modifikator ( Demo ):regex = /(?s)(.*)<FooBar>/
(?s)
Modifikator ( Demo ) verwenden:"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
[^]
oder Problemumgehung [\d\D]
/ [\w\W]
/ [\s\S]
( Demo ):s.match(/([\s\S]*)<FooBar>/)[1]
std::regex
) Verwenden Sie [\s\S]
oder die JS-Problemumgehungen ( Demo ):regex rex(R"(([\s\S]*)<FooBar>)");
vba vbscript- Verwenden Sie den gleichen Ansatz wie in JavaScript ([\s\S]*)<Foobar>
. ( HINWEIS : Die MultiLine
Eigenschaft des
RegExp
Objekts wird manchmal fälschlicherweise als die Option angesehen, .
Übereinstimmungen über Zeilenumbrüche hinweg zuzulassen , während tatsächlich nur das Verhalten ^
und das $
Verhalten so geändert werden, dass es mit dem Anfang / Ende von Zeilen und nicht mit Zeichenfolgen übereinstimmt , wie in JS-Regex ) Verhalten.)
Rubin- Verwenden /m
Sie den Modifikator MULTILINE ( Demo ):s[/(.*)<Foobar>/m, 1]
(?s)
: regmatches(x, regexec("(?s)(.*)<FooBar>",x, perl=TRUE))[[1]][2]
( Demo )stringr
/ stringi
Regex-Funktionen, die mit der ICU-Regex-Engine betrieben werden, verwenden außerdem (?s)
: stringr::str_match(x, "(?s)(.*)<FooBar>")[,2]
( Demo )(?s)
zu Beginn den Inline-Modifikator ( Demo ):re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
dotMatchesLineSeparators
den (?s)
Inline-Modifikator oder übergeben Sie ihn (einfacher) an das Muster:let rx = "(?s)(.*)<Foobar>"
(?s)
funktioniert am einfachsten, aber hier ist, wie die Option verwendet werden kann :NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern
options:NSRegularExpressionDotMatchesLineSeparators error:®exError];
(?s)
Modifikator ( Demo ): "(?s)(.*)<Foobar>"
(in Google Spreadsheets, =REGEXEXTRACT(A2,"(?s)(.*)<Foobar>")
)ANMERKUNGEN ZU(?s)
:
In den meisten Nicht-POSIX-Engines kann der (?s)
Inline-Modifikator (oder die eingebettete Flag-Option) verwendet werden, um zu erzwingen .
, dass Zeilenumbrüche übereinstimmen.
Wenn es am Anfang des Musters platziert wird, (?s)
ändert sich das Verhalten aller .
im Muster. Wenn das (?s)
irgendwo nach dem Anfang platziert wird, sind nur diejenigen .
betroffen, die sich rechts davon befinden, es sei denn, dies ist ein an Python übergebenes Muster re
. In Python re
ist unabhängig vom (?s)
Speicherort das gesamte Muster .
betroffen. Der (?s)
Effekt wird mit beendet (?-s)
. Eine geänderte Gruppe kann verwendet werden, um nur einen bestimmten Bereich eines Regex-Musters zu beeinflussen (z. B. Delim1(?s:.*?)\nDelim2.*
wird die erste .*?
Übereinstimmung über Zeilenumbrüche hinweg und die zweite .*
nur mit dem Rest der Zeile übereinstimmen).
POSIX Hinweis :
In nicht-POSIX regex Motoren passen jede char, [\s\S]
/ [\d\D]
/ [\w\W]
Konstrukte verwendet werden können.
Entspricht in POSIX [\s\S]
keinem Zeichen (wie in JavaScript oder einer Nicht-POSIX-Engine), da Regex-Escape-Sequenzen in Klammerausdrücken nicht unterstützt werden. [\s\S]
wird als Klammerausdrücke analysiert, die einem einzelnen Zeichen entsprechen, \
oder s
oder S
.
#define MOD regex_constants::perl | boost::regex::no_mod_s | boost::regex::no_mod_m
für ihre Regex-Flags fest, um dies widerzuspiegeln. Und der Schiedsrichter ist immer der Inline-Modifikator. Wo (?-sm)(?s).*
zurückgesetzt.
.
mit jedem Zeichen dort übereinstimmt (einschließlich Zeilenumbrüchen). Sehen Sie sich diese Online-Bash-Demo an .
Go
in die Antwort!
Wenn Sie die Eclipse-Suche verwenden, können Sie die Option "DOTALL" aktivieren, um '.' stimmen mit jedem Zeichen überein, einschließlich Zeilenbegrenzern: Fügen Sie einfach "(? s)" am Anfang Ihrer Suchzeichenfolge hinzu. Beispiel:
(?s).*<FooBar>
(?s)
=>(?m)
In vielen Regex-Dialekten /[\S\s]*<Foobar>/
wird genau das getan, was Sie wollen. Quelle
([\s\S]*)<FooBar>
Der Punkt stimmt mit allen außer Zeilenumbrüchen (\ r \ n) überein. Verwenden Sie also \ s \ S, das ALLEN Zeichen entspricht.
[text rangeOfString:regEx options:NSRegularExpressionSearch]
. Vielen Dank!
<FooBar>
In Ruby RubinSie können die m
Option ' ' (mehrzeilig) verwenden:
/YOUR_REGEXP/m
Weitere Informationen finden Sie in der Regexp-Dokumentation auf ruby-doc.org.
wir können auch verwenden
(.*?\n)*?
um alles zusammenzubringen, einschließlich Newline ohne Gier
Dadurch wird die neue Zeile optional
(.*?|\n)*?
"."
passt normalerweise nicht zu Zeilenumbrüchen. Bei den meisten Regex-Engines können Sie das S
Flag (auch DOTALL
und genannt SINGLELINE
) hinzufügen , damit "."
auch Zeilenumbrüche übereinstimmen. Wenn das fehlschlägt, können Sie so etwas tun [\S\s]
.
/(.*)<FooBar>/s
Das s bewirkt, dass Dot (.) mit den Wagenrückläufen übereinstimmt
s
Flags sind in PCRE vorhanden, der vollständigsten Engine (verfügbar in Perl und PHP). PCRE hat 10 Flags (und viele andere Funktionen), während JavaScript nur 3 Flags ( gmi
) hat.
In Java-basierten regulären Ausdrücken können Sie verwenden [\s\S]
s
Flag einfach in Java zum Muster hinzufügen können und JavaScript das s
Flag nicht hat .
Beachten Sie, dass (.|\n)*
dies weniger effizient sein kann als (zum Beispiel) [\s\S]*
(wenn die regulären Ausdrücke Ihrer Sprache solche Escapezeichen unterstützen) und als zu finden, wie der Modifikator angegeben wird, der erstellt wird. passen auch zu Zeilenumbrüchen. Oder Sie können mit POSIXy Alternativen wie gehen [[:space:][:^space:]]*
.
Verwenden Sie den Mustermodifikator sU, um die gewünschte Übereinstimmung in PHP zu erzielen.
preg_match('/(.*)/sU',$content,$match);
http://dreamluverz.com/developers-tools/regex-match-all-including-new-line http://php.net/manual/en/reference.pcre.pattern.modifiers.php
Im Zusammenhang mit der Verwendung in Sprachen wirken reguläre Ausdrücke auf Zeichenfolgen und nicht auf Zeilen. Sie sollten also in der Lage sein, den regulären Ausdruck normal zu verwenden, vorausgesetzt, die Eingabezeichenfolge enthält mehrere Zeilen.
In diesem Fall stimmt der angegebene reguläre Ausdruck mit der gesamten Zeichenfolge überein, da "<FooBar>" vorhanden ist. Abhängig von den Besonderheiten der Regex-Implementierung ist der Wert von $ 1 (erhalten aus "(. *)") Entweder "fghij" oder "abcde \ nfghij". Wie andere bereits gesagt haben, können Sie bei einigen Implementierungen steuern, ob das "." passt zur Newline und gibt Ihnen die Wahl.
Die zeilenbasierte Verwendung regulärer Ausdrücke wird normalerweise für Befehlszeilendinge wie egrep verwendet.
Ich hatte das gleiche Problem und löste es wahrscheinlich nicht auf die beste Weise, aber es funktioniert. Ich habe alle Zeilenumbrüche ersetzt, bevor ich mein richtiges Match gemacht habe:
mystring= Regex.Replace(mystring, "\r\n", "")
Ich manipuliere HTML, sodass Zeilenumbrüche in diesem Fall für mich nicht wirklich wichtig sind.
Ich habe alle oben genannten Vorschläge ohne Glück ausprobiert. Ich verwende .Net 3.5 FYI
(\s|\S)
scheint den Trick für mich zu tun!
(?s)
um .
Zeichen anzupassen . Verwenden Sie (\s|\S)
diese Option nicht , um die Leistung zu beeinträchtigen.
In Javascript können Sie mit [^] * nach null bis unendlichen Zeichen suchen, einschließlich Zeilenumbrüchen.
$("#find_and_replace").click(function() {
var text = $("#textarea").val();
search_term = new RegExp("[^]*<Foobar>", "gi");;
replace_term = "Replacement term";
var new_text = text.replace(search_term, replace_term);
$("#textarea").val(new_text);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="find_and_replace">Find and replace</button>
<br>
<textarea ID="textarea">abcde
fghij<Foobar></textarea>
allgemein . stimmt nicht mit Zeilenumbrüchen überein, versuchen Sie es also((.|\n)*)<foobar>
\r
.:((?:.|\r?\n)*)<foobar>
Ich wollte einen bestimmten if-Block in Java finden
...
...
if(isTrue){
doAction();
}
...
...
}
Wenn ich die regExp benutze
if \(isTrue(.|\n)*}
Es enthielt die schließende Klammer für den Methodenblock, den ich verwendet habe
if \(!isTrue([^}.]|\n)*}
um die schließende Klammer vom Platzhalter-Match auszuschließen.
Oft müssen wir einen Teilstring mit einigen Schlüsselwörtern ändern, die über Zeilen vor dem Teilstring verteilt sind. Betrachten Sie ein XML-Element:
<TASK>
<UID>21</UID>
<Name>Architectural design</Name>
<PercentComplete>81</PercentComplete>
</TASK>
Angenommen, wir möchten die 81 auf einen anderen Wert ändern, z. B. 40. Zuerst identifizieren .UID.21..UID.
, dann alle Zeichen einschließlich \n
bis überspringen .PercentCompleted.
. Das Muster für reguläre Ausdrücke und die Ersetzungsspezifikation sind:
String hw = new String("<TASK>\n <UID>21</UID>\n <Name>Architectural design</Name>\n <PercentComplete>81</PercentComplete>\n</TASK>");
String pattern = new String ("(<UID>21</UID>)((.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
String replaceSpec = new String ("$1$2$440$6");
//note that the group (<PercentComplete>) is $4 and the group ((.|\n)*?) is $2.
String iw = hw.replaceFirst(pattern, replaceSpec);
System.out.println(iw);
<TASK>
<UID>21</UID>
<Name>Architectural design</Name>
<PercentComplete>40</PercentComplete>
</TASK>
Die Untergruppe (.|\n)
ist wahrscheinlich die fehlende Gruppe $3
. Wenn wir es nicht-Capturing, indem (?:.|\n)
dann das $3
ist (<PercentComplete>)
. So kann das Muster und replaceSpec
auch sein:
pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")
und der Austausch funktioniert korrekt wie zuvor.
Wenn Sie in Powershell normalerweise nach drei aufeinander folgenden Zeilen suchen, sieht es folgendermaßen aus:
$file = get-content file.txt -raw
$pattern = 'lineone\r\nlinetwo\r\nlinethree\r\n' # "windows" text
$pattern = 'lineone\nlinetwo\nlinethree\n' # "unix" text
$pattern = 'lineone\r?\nlinetwo\r?\nlinethree\r?\n' # both
$file -match $pattern
# output
True
Seltsamerweise wäre dies Unix-Text an der Eingabeaufforderung, aber Windows-Text in einer Datei:
$pattern = 'lineone
linetwo
linethree
'
So drucken Sie die Zeilenenden aus:
'lineone
linetwo
linethree
' -replace "`r",'\r' -replace "`n",'\n'
# output
lineone\nlinetwo\nlinethree\n
Eine Möglichkeit wäre, die s
Flagge zu verwenden (genau wie die akzeptierte Antwort):
/(.*)<FooBar>/s
Eine zweite Möglichkeit wäre die Verwendung des m
(mehrzeiligen) Flags und eines der folgenden Muster:
/([\s\S]*)<FooBar>/m
oder
/([\d\D]*)<FooBar>/m
oder
/([\w\W]*)<FooBar>/m
jex.im visualisiert reguläre Ausdrücke: