Na przykład to wyrażenie regularne
(.*)<FooBar>
będzie pasować:
abcde<FooBar>
Ale jak mogę dopasować go do wielu linii?
abcde
fghij<FooBar>
Na przykład to wyrażenie regularne
(.*)<FooBar>
będzie pasować:
abcde<FooBar>
Ale jak mogę dopasować go do wielu linii?
abcde
fghij<FooBar>
Odpowiedzi:
To zależy od języka, ale powinien istnieć modyfikator, który możesz dodać do wzorca wyrażenia regularnego. W PHP jest to:
/(.*)<FooBar>/s
Litera s na końcu powoduje, że kropka dopasowuje wszystkie znaki, w tym znaki nowej linii.
s
modyfikatora. Zamiast tego zrób [^]*
dla tego samego efektu.
m
modyfikatora
Spróbuj tego:
((.|\n)*)<FooBar>
Mówi w zasadzie „dowolny znak lub nowa linia” powtarzane zero lub więcej razy.
((.|\n|\r)*)<FooBar>
[\s\S]*
lub (?s).*
.
Pytanie brzmi: czy .
wzór może pasować do dowolnej postaci? Odpowiedź różni się w zależności od silnika. Główną różnicą jest to, czy wzorzec jest używany przez bibliotekę wyrażeń regularnych POSIX, czy nie.
Specjalna uwaga na temat wzory lua: nie są uważane za wyrażenia regularne, ale .
pasują do każdego tam znaku, tak samo jak silniki oparte na POSIX.
Kolejna uwaga na temat Matlab i oktawa: .
domyślnie dopasowuje dowolny znak ( demo ): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match');
( tokens
zawiera abcde\n fghij
element).
Również we wszystkich podnieśćGramatyka wyrażeń regularnych kropka domyślnie dopasowuje podział linii. Gramatyka ECMAScript doładowania pozwala na wyłączenie tego za pomocą regex_constants::no_mod_m
( źródła ).
Jeśli chodzi o wyrocznia(jest oparty na POSIX), użyj n
opcji ( demo ):select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual
Silniki oparte na POSIX :
Zwykły .
już pasuje do podziałów linii, nie trzeba używać żadnych modyfikatorów, patrzgrzmotnąć( demo ).
The tcl( demo ),postgresql( demo ),r(TRE, domyślny silnik bazowy R z nie perl=TRUE
, dla bazowego R z perl=TRUE
lub dla wzorów stringr / stringi , użyj (?s)
modyfikatora wbudowanego) ( demo ) również traktuj .
to samo.
Jednak większość narzędzi opartych na POSIX przetwarza dane wejściowe linia po linii. Dlatego .
nie pasuje do podziałów linii tylko dlatego, że nie są one objęte zakresem. Oto kilka przykładów, jak to zmienić:
sed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/'
( H;1h;$!d;x;
zapisuje plik w pamięci). Jeśli trzeba uwzględnić całe linie, sed '/start_pattern/,/end_pattern/d' file
(usunięcie od początku zakończy się dołączeniem pasujących linii) lub sed '/start_pattern/,/end_pattern/{{//!d;};}' file
(z wyłączeniem pasujących linii) można rozważyć.perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str"
( -0
umieszcza cały plik w pamięci, -p
drukuje plik po zastosowaniu skryptu podanego przez -e
). Zauważ, że użycie -000pe
spowoduje zepsucie pliku i aktywację „trybu akapitowego”, w którym Perl używa kolejnych znaków nowej linii ( \n\n
) jako separatora rekordów.grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file
. Tutaj z
włącza (?s)
rozmycie plików, włącza tryb DOTALL dla .
wzorca, (?i)
włącza tryb bez rozróżniania wielkości liter, \K
pomija do tej pory dopasowany tekst, *?
jest leniwym kwantyfikatorem, (?=<Foobar>)
dopasowuje wcześniejszą lokalizację <Foobar>
.pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file
( M
umożliwia tutaj rozmazanie plików). Uwaga pcregrep
jest dobrym rozwiązaniem dla grep
użytkowników Mac OS .Silniki inne niż POSIX :
s
modyfikatora PCRE_DOTALL : preg_match('~(.*)<Foobar>~s', $s, $m)
( demo )RegexOptions.Singleline
flagi ( demo ): var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;
var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;
(?s)
opcji wbudowanej:$s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]
s
modyfikatora (lub (?s)
wersji inline na początku) ( demo ):/(.*)<FooBar>/s
re.DOTALL
(lub re.S
) flag lub (?s)
wbudowanego modyfikatora ( demo ): m = re.search(r"(.*)<FooBar>", s, flags=re.S)
(a następnie if m:
, print(m.group(1))
)Pattern.DOTALL
modyfikatora (lub wbudowanej (?s)
flagi) ( demo ):Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
(?s)
wbudowanego modyfikatora ( demo ):regex = /(?s)(.*)<FooBar>/
(?s)
modyfikatora ( demo ):"(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
[^]
lub obejścia [\d\D]
/ [\w\W]
/ [\s\S]
( demo ):s.match(/([\s\S]*)<FooBar>/)[1]
std::regex
) Użyj [\s\S]
lub obejścia JS ( wersja demonstracyjna ):regex rex(R"(([\s\S]*)<FooBar>)");
vba vbscript- Użyj tego samego podejścia jak w JavaScripcie ([\s\S]*)<Foobar>
. ( UWAGA : MultiLine
Właściwość
RegExp
obiektu jest czasami mylnie uważana za opcję umożliwiającą .
dopasowanie między podziałami linii, podczas gdy w rzeczywistości zmienia ona tylko zachowanie ^
i $
dopasowuje początek / koniec linii zamiast ciągów znaków , tak jak w wyrażeniu regularnym JS ) zachowanie).
rubin- Użyj modyfikatora /m
MULTILINE ( demo ):s[/(.*)<Foobar>/m, 1]
(?s)
: regmatches(x, regexec("(?s)(.*)<FooBar>",x, perl=TRUE))[[1]][2]
( demo )stringr
/ stringi
regex, które są zasilane silnikiem regex ICU, również użyj (?s)
: stringr::str_match(x, "(?s)(.*)<FooBar>")[,2]
( demo )(?s)
na początku ( demo ):re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
dotMatchesLineSeparators
lub (łatwiej) przekaż (?s)
modyfikator wbudowany do wzorca:let rx = "(?s)(.*)<Foobar>"
(?s)
działa najłatwiej, ale oto jak można użyć tej opcji :NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern
options:NSRegularExpressionDotMatchesLineSeparators error:®exError];
(?s)
modyfikatora ( demo ): "(?s)(.*)<Foobar>"
(w arkuszach kalkulacyjnych Google =REGEXEXTRACT(A2,"(?s)(.*)<Foobar>")
)UWAGI NA(?s)
:
W większości silników innych niż POSIX (?s)
można użyć wbudowanego modyfikatora (lub wbudowanej opcji flagi) w celu wymuszenia .
dopasowania podziałów linii.
Umieszczony na początku wzoru (?s)
zmienia zachowanie wszystkich elementów .
we wzorze. Jeśli (?s)
zostanie umieszczony gdzieś po początku, .
wpłynie to tylko na te , które znajdują się po jego prawej stronie, chyba że jest to wzór przekazany Pythonowi re
. W Pythonie re
, niezależnie od (?s)
lokalizacji, .
wpływa to na cały wzorzec . (?s)
Efekt jest zatrzymywany za pomocą (?-s)
. Zmodyfikowanej grupy można użyć, aby wpływała tylko na określony zakres wzorca wyrażenia regularnego (np. Dopasuje Delim1(?s:.*?)\nDelim2.*
pierwsze .*?
dopasowanie do nowych linii, a drugie .*
dopasuje tylko resztę linii).
Uwaga POSIX :
W silnikach wyrażeń regularnych innych niż POSIX, aby dopasować dowolny znak, można użyć konstrukcji [\s\S]
/ [\d\D]
/ [\w\W]
.
W POSIX [\s\S]
nie pasuje do żadnego znaku (jak w JavaScript lub innym silniku innym niż POSIX), ponieważ sekwencje specjalne wyrażeń regularnych nie są obsługiwane w wyrażeniach nawiasów. [\s\S]
jest analizowany jako wyrażenia w nawiasach pasujące do jednego znaku \
lub s
lub S
.
#define MOD regex_constants::perl | boost::regex::no_mod_s | boost::regex::no_mod_m
dla swoich flag wyrażenia regularnego, aby to odzwierciedlić. A arbitrem są zawsze wbudowane modyfikatory. Gdzie (?-sm)(?s).*
resetuje się.
.
dopasowuje dowolny znak tam (w tym podział wiersza). Zobacz to demo online Bash .
Go
w odpowiedzi!
Jeśli korzystasz z wyszukiwania Eclipse, możesz włączyć opcję „DOTALL”, aby utworzyć „.” dopasuj dowolny znak, w tym ograniczniki linii: po prostu dodaj „(? s)” na początku szukanego ciągu. Przykład:
(?s).*<FooBar>
(?s)
=>(?m)
W wielu dialektach regularnych /[\S\s]*<Foobar>/
zrobi to, co chcesz. Źródło
([\s\S]*)<FooBar>
Kropka pasuje do wszystkich oprócz znaków nowej linii (\ r \ n). Więc użyj \ s \ S, który będzie pasował do WSZYSTKICH znaków.
[text rangeOfString:regEx options:NSRegularExpressionSearch]
. Dzięki!
<FooBar>
W Ruby rubinmożesz użyć opcji „ m
” (wielowierszowa):
/YOUR_REGEXP/m
Aby uzyskać więcej informacji, zobacz dokumentację Regexp na ruby-doc.org.
możemy również użyć
(.*?\n)*?
dopasować wszystko, w tym nową linię bez zachłanności
Dzięki temu nowa linia będzie opcjonalna
(.*?|\n)*?
"."
zwykle nie pasuje do podziałów linii. Większość silników wyrażeń regularnych pozwala na dodanie opcji S
-flag (nazywanej także DOTALL
i SINGLELINE
), aby "."
dopasować także nowe znaki. Jeśli to się nie powiedzie, możesz zrobić coś takiego [\S\s]
.
/(.*)<FooBar>/s
s powoduje, że kropka (.) dopasowuje zwroty karetki
s
flagi istnieje w PCRE, najbardziej kompletny silnik (dostępne w Perl i PHP). PCRE ma 10 flag (i wiele innych funkcji), podczas gdy JavaScript ma tylko 3 flagi ( gmi
).
W wyrażeniach regularnych opartych na języku Java można używać [\s\S]
s
flagę do wzorca w Javie, a JavaScript nie ma s
flagi.
Zauważ, że (.|\n)*
może to być mniej wydajne niż (na przykład) [\s\S]*
(jeśli wyrażenia regularne w Twoim języku obsługują takie znaki ucieczki) i niż znalezienie sposobu na określenie modyfikatora, który czyni. pasują również do nowych linii. Możesz też skorzystać z alternatyw POSIXy, takich jak [[:space:][:^space:]]*
.
Użyj modyfikatora wzorca sU uzyska pożądane dopasowanie w PHP.
preg_match('/(.*)/sU',$content,$match);
http://dreamluverz.com/developers-tools/regex-match-all-inclusion-new-line http://php.net/manual/en/reference.pcre.pattern.modifiers.php
W kontekście użycia w językach, wyrażenia regularne działają na ciągi, a nie na wiersze. Powinieneś być w stanie normalnie używać wyrażenia regularnego, zakładając, że łańcuch wejściowy ma wiele wierszy.
W takim przypadku podany regex będzie pasował do całego łańcucha, ponieważ „<FooBar>” jest obecny. W zależności od specyfiki implementacji wyrażenia regularnego wartość 1 USD (uzyskana z „(. *)”) Będzie albo „fghij”, albo „abcde \ nfghij”. Jak powiedzieli inni, niektóre implementacje pozwalają kontrolować, czy „.” dopasuje nową linię, dając ci wybór.
Wyrażenia regularne oparte na liniach są zwykle używane do wiersza poleceń, np. Egrep.
Miałem ten sam problem i rozwiązałem go prawdopodobnie nie w najlepszy sposób, ale działa. Zastąpiłem wszystkie podziały linii, zanim wykonałem mój prawdziwy mecz:
mystring= Regex.Replace(mystring, "\r\n", "")
Manipuluję HTML, więc podział wiersza tak naprawdę nie ma dla mnie znaczenia w tym przypadku.
Wypróbowałem wszystkie powyższe sugestie bez powodzenia, używam .Net 3.5 FYI
(\s|\S)
wydaje mi się, że załatwił sprawę!
(?s)
aby .
dopasować dowolne znaki. Nie używaj (\s|\S)
, aby spowolnić działanie.
W Javascripcie możesz użyć [^] * do wyszukiwania od zera do nieskończonych znaków, w tym do łamania linii.
$("#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>
ogólnie. nie pasuje do nowych linii, więc spróbuj((.|\n)*)<foobar>
\r
:((?:.|\r?\n)*)<foobar>
Często musimy zmodyfikować podciąg za pomocą kilku słów kluczowych rozmieszczonych w liniach poprzedzających podłańcuch. Rozważ element xml:
<TASK>
<UID>21</UID>
<Name>Architectural design</Name>
<PercentComplete>81</PercentComplete>
</TASK>
Załóżmy, że chcemy zmodyfikować 81 do innej wartości, powiedzmy 40. Najpierw zidentyfikuj .UID.21..UID.
, a następnie pomiń wszystkie znaki, w tym \n
kasę .PercentCompleted.
. Wzorem wyrażeń regularnych i specyfikacją zamiany są:
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>
Podgrupa (.|\n)
jest prawdopodobnie brakującą grupą $3
. Jeśli sprawimy, że do tej (?:.|\n)
pory nie będzie przechwytywany, to $3
znaczy, że jest (<PercentComplete>)
. Więc wzór i replaceSpec
może być również:
pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")
a zamiennik działa poprawnie jak poprzednio.
Zwykle wyszukiwanie trzech kolejnych wierszy w PowerShell wygląda następująco:
$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
Dziwnie, to byłby tekst unix po znaku zachęty, ale tekst Windows w pliku:
$pattern = 'lineone
linetwo
linethree
'
Oto sposób wydrukowania zakończeń linii:
'lineone
linetwo
linethree
' -replace "`r",'\r' -replace "`n",'\n'
# output
lineone\nlinetwo\nlinethree\n
Jednym ze sposobów byłoby użycie s
flagi (podobnie jak zaakceptowana odpowiedź):
/(.*)<FooBar>/s
Drugim sposobem byłoby użycie m
flagi (wielowierszowej) i dowolnego z następujących wzorców:
/([\s\S]*)<FooBar>/m
lub
/([\d\D]*)<FooBar>/m
lub
/([\w\W]*)<FooBar>/m
jex.im wizualizuje wyrażenia regularne: