Regex Dopasuj wszystkie znaki między dwoma łańcuchami


434

Przykład: „To proste zdanie”.

Chcę dopasować każdą postać między „To jest” a „zdaniem”. Podziały linii należy zignorować. Nie mogę ustalić poprawnej składni.


11
Możesz wskazać, w jakim środowisku używasz Regex. Mogą występować różnice w zależności od tego, co rozumiesz przez „ignorowanie” podziałów linii.
Andrew Barber

Odpowiedzi:


646

Na przykład

(?<=This is)(.*)(?=sentence)

Regexr

Użyłem lookbehind (?<=)i patrzyłem w przyszłość (?=), aby „To jest” i „zdanie” nie było uwzględnione w dopasowaniu, ale to zależy od twojego przypadku użycia, możesz też po prostu napisać This is(.*)sentence.

Ważne jest tutaj, aby aktywować tryb „dotall” silnika regex, tak aby pasował .on do nowej linii. Ale jak to zrobisz, zależy od silnika wyrażeń regularnych.

Następną rzeczą jest, jeśli używasz .*lub .*?. Pierwszy jest chciwy i będzie pasował do ostatniego „zdania” w twoim ciągu, drugi będzie leniwy i będzie pasował do następnego „zdania” w twoim ciągu.

Aktualizacja

Regexr

This is(?s)(.*)sentence

Gdzie (? S) włącza modyfikator dotall, .dopasowując znaki nowego wiersza.

Aktualizacja 2:

(?<=is \()(.*?)(?=\s*\))

pasuje do Twojego przykładu „To jest (proste) zdanie”. Zobacz tutaj na Regexr


@ tchrist, przepraszam, że musiałem to sprawdzić. Czy rozumiem to poprawnie i This is(?s)(.*)sentencedziałałoby?
stema

@stema: Tak, powinno to działać, aby włączyć tryb „wszystkie kropki” w większości bibliotek wyrażeń regularnych.
tchrist

1
To w większości rozwiązało mój problem, ale jak dołączyć do wzorca biały znak? Próbowałem: „(. *?) ())” W celu dopasowania do „)” na końcu sekwencji, ale to nie zadziałało.
0xbadf00d

28
Tylko jedna uwaga - regexr mówi teraz, że lookbehind nie jest obsługiwany w javascript
Kovo

2
Czy istnieje sposób radzenia sobie z powtarzającymi się wystąpieniami tego podziału w bloku tekstu? Na przykład: „To tylko proste zdanie. Oto kilka dodatkowych rzeczy. To tylko proste zdanie. A oto kilka innych rzeczy. To tylko proste zdanie.”. Obecnie dopasowuje cały ciąg, a nie każdą instancję.
jzadra

181

Potrzebny leniwy kwantyfikator

Wznowienie tego pytania, ponieważ wyrażenie regularne w zaakceptowanej odpowiedzi nie wydaje mi się całkiem poprawne. Dlaczego? Ponieważ

(?<=This is)(.*)(?=sentence)

dopasuje my first sentence. This is my secondsięThis is my first sentence. This is my second sentence.

Zobacz demo .

Potrzebujesz leniwego kwantyfikatora między tymi dwoma spojrzeniami. Dodanie ?gwiazdy powoduje, że gwiazda jest leniwa.

To pasuje do tego, co chcesz:

(?<=This is).*?(?=sentence)

Zobacz demo . Usunąłem grupę przechwytywania, która nie była potrzebna.

Tryb DOTALL, aby dopasować podział linii

Zauważ, że w wersji demo „kropka dopasowuje tryb podziału linii” (aka) kropka-wszystko jest ustawiona (zobacz, jak włączyć DOTALL w różnych językach ). W wielu odmianach (?s)wyrażeń regularnych możesz ustawić go za pomocą modyfikatora online , zmieniając wyrażenie w:

(?s)(?<=This is).*?(?=sentence)

Odniesienie


Masz rację co do grupy przechwytywania. Nie wiem, dlaczego to zrobiłem. Ale różnica między .*i .*?jest również wyjaśniona w mojej odpowiedzi (akapit przed „Aktualizacją”). Więc nie sądzę, że moja odpowiedź jest niepoprawna.
stema

2
@stema Przepraszam za dręczenie, podczas gdy przeglądam niektóre z twoich wczorajszych odpowiedzi, to jedyna, która sprawiła, że ​​zadrżałem. :) Zmiękczyłem pierwszą linię od is incorrectdo doesn't seem quite correct to me... Mam nadzieję, że nie sprawisz, że się skręcisz, prawdopodobnie tylko różnica w postrzeganiu tego, jaki powinien być regex dla tak dużego ruchu.
zx81

39

Spróbuj This is[\s\S]*sentence, działa w javascript


jak wykonać leniwe wyszukiwanie w ten sposób?
AGamePlayer

4
@AwQiruiGuo to samo co powyżej. [\s\S]*?(zwany także: non-chciwy symbol zastępczy)
phil294


13

Użyj tego: (?<=beginningstringname)(.*\n?)(?=endstringname)


Nie wiem, dlaczego wszystkie głosy w górę, pozwala to na podział linii 0-1, a podział linii musi nastąpić bezpośrednio przedendstringname
OGHaza

Uważam, że warto usunąć początek wiersza dziennika (znacznik czasu itp.). Użyłem nowej linii dla łańcucha początkowego i „at” dla łańcucha końcowego.
Stan

2

Na wypadek, gdyby ktoś szukał takiego przykładu w kontekście Jenkinsa. Analizuje build.log, a jeśli znajdzie dopasowanie, nie powiedzie się kompilacja z dopasowaniem.

import java.util.regex.Matcher;
import java.util.regex.Pattern;

node{    
    stage("parse"){
        def file = readFile 'build.log'

        def regex = ~"(?s)(firstStringToUse(.*)secondStringToUse)"
        Matcher match = regex.matcher(file)
        match.find() {
            capturedText = match.group(1)
            error(capturedText)
        }
    }
}


0

Podniosły tekst 3x

W wysublimowanym tekście po prostu wpisujesz dwa słowa, które chcesz zachować, na przykład w twoim przypadku

„To jest” i „zdanie”

i piszesz. * pomiędzy

to znaczy This is .* sentence

i to powinno ci dobrze zrobić


Nie jestem pewien, czy pytanie dotyczy tego, jak to zrobić w Sublime Text, ale głównie działa w Sublime Text. Nie działa, gdy dochodzi do podziału między „To jest” a „zdanie”. Również wysublimowany tekst wybiera „To jest” i „Zdanie”, a nie tylko tekst między tymi dwoma ciągami.
Dylan Kinnett

0

Oto jak to zrobiłem:
To było dla mnie łatwiejsze niż próbowanie znalezienia konkretnego wyrażenia regularnego, które jest konieczne.

int indexPictureData = result.IndexOf("-PictureData:");
int indexIdentity = result.IndexOf("-Identity:");
string returnValue = result.Remove(indexPictureData + 13);
returnValue = returnValue + " [bytecoderemoved] " + result.Remove(0, indexIdentity); ` 

0

w celu szybkiego wyszukiwania w VIM możesz użyć polecenia Vim Control: / To jest. * \ _. * zdanie


0

Wylądowałem tutaj, szukając wyrażenia regularnego, aby przekonwertować tę składnię wydruku między drukowanym „ciągiem”, w Pythonie 2 w starych skryptach za pomocą: print („ciąg”), dla Python3. Działa dobrze, w przeciwnym razie użyj 2to3.py do dodatkowych konwersji. Oto moje rozwiązanie dla innych:

Wypróbuj to na Regexr.com (z jakiegoś powodu nie działa w NP ++):

find:     (?<=print)( ')(.*)(')
replace: ('$2')

dla zmiennych:

(?<=print)( )(.*)(\n)
('$2')\n

dla etykiety i zmiennej:

(?<=print)( ')(.*)(',)(.*)(\n)
('$2',$4)\n

Jak zamienić cały „ciąg” wydruku w Python2 na print („ciąg”) dla Python3?


0

To zadziałało dla mnie (używam VS Code ):

dla: This is just\na simple sentence

Posługiwać się: This .+ sentence


0

RegEx, aby dopasować wszystko między dwoma łańcuchami przy użyciu podejścia Java.

List<String> results = new ArrayList<>(); //For storing results
String example = "Code will save the world";

Użyjmy obiektów Pattern i Matcher, aby użyć RegEx (. ?) * .

Pattern p = Pattern.compile("Code "(.*?)" world");   //java.util.regex.Pattern;
Matcher m = p.matcher(example);                      //java.util.regex.Matcher;

Ponieważ Matcher może zawierać więcej niż jedno dopasowanie, musimy zapętlić wyniki i zapisać je.

while(m.find()){   //Loop through all matches
   results.add(m.group()); //Get value and store in collection.
}

Ten przykład będzie zawierał tylko słowo „zapisze” słowo, ale w większym tekście prawdopodobnie znajdzie więcej dopasowań.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.