Regex: dopasuj wszystko oprócz określonego wzorca

310

Potrzebuję wyrażenia regularnego zdolnego do dopasowania wszystkiego oprócz łańcucha rozpoczynającego się od określonego wzorca (konkretnie index.phpi tego, co następuje, jak index.php?id=2342343)

pistacchio
źródło
A jaki konkretny wzór nie chcesz dopasować?
Dominic Rodger,
2
Czy istnieje powód, dla którego nie możesz dopasować się do wzorca i nie zrobić czegoś, jeśli łańcuch pasuje do tego?
Thomas Owens,
@ThomasOwens: To zależy. To zależy od tego, która część wyrażenia będzie zanegowana. Jeśli całe wyrażenie ma być zanegowane, masz rację. Na przykład, jeśli chcesz zakodować „jeśli ciąg nie zawiera„ Bruce ”jako podłańcucha, zrób coś”, użyjesz po prostu / Bruce / i umieścisz negację w instrukcji if, poza wyrażeniem regularnym . Ale może być tak, że chciałbyś zanegować niektóre podwyrażenia. Powiedzmy, że szukasz czegoś takiego jak imię, gdzie imię to Bruce, a nazwisko to wszystko oprócz XYZ, gdzie XYZ to nazwisko niektórych celebrytów o imieniu Bruce.
mathheadinclouds

Odpowiedzi:

250

Nie jestem ekspertem od wyrażeń regularnych, ale myślę, że od samego początku możesz użyć negatywnego spojrzenia, np. ^(?!foo).*$Nie powinieneś pasować do niczego, zaczynając od foo.

Cat Plus Plus
źródło
7
Z grep użyj -P, aby włączyć lookahead.
Seppo Enarvi
Jeśli pożądane zachowanie nie jest zgodne z „foo” lub „bar”, sprawdź tę odpowiedź: stackoverflow.com/a/2404330/874824
dave_k_smith
15
Ta odpowiedź jest błędna, pokazuje to szybki test. Myślę, że miałeś na myśli ^((?!foo).)*$( stackoverflow.com/a/406408/3964381 )
gilad mayani
4
Czy mógłbyś wyjaśnić użyte symbole i dlaczego?
rotimi-best
339

Regex: dopasuj wszystko oprócz :

Uwaga demonstracyjna : nowa linia \njest używana w negowanych klasach znaków w demonstracjach, aby uniknąć przepełnienia dopasowania do sąsiednich linii. Nie są one konieczne podczas testowania pojedynczych ciągów.

Uwaga kotwicy : W wielu językach użyj \Ado zdefiniowania jednoznacznego początku łańcucha, a \z(w Pythonie jest to \Zw JavaScript $jest OK), aby zdefiniować sam koniec łańcucha.

Uwaga dot : W wielu smakach (ale nie POSIX, TRE, TCL), .pasuje do dowolnego znaku, ale znak nowego wiersza . Upewnij się, że używasz odpowiedniego modyfikatora DOTALL ( /sw PCRE / Boost / .NET / Python / Java i /mRuby), .aby dopasować dowolny znak, w tym nowy wiersz.

Backslash Uwaga : W językach, gdzie trzeba zadeklarować wzory z ciągów C pozwalających sekwencje (jak \ndla nowej linii), trzeba podwoić backslashy uciekających tak specjalne znaki, że silnik mógłby traktować je jako znaki dosłowne (na przykład w Javie, world\.będzie zadeklarowane jako "world\\."lub użyj klasy znaków:) "world[.]". Używaj nieprzetworzonych literałów łańcuchowych (Python r'\bworld\b'), dosłownych literałów łańcuchowych C # @"world\."lub ukośnych ciągów znaków / wyrażeń regularnych, takich jak /world\./.

Wiktor Stribiżew
źródło
Świetnie napisz! W przypadku „łańcucha (nie) równego jakiemuś łańcuchowi”, na przykład ^(?!foo$), dlaczego znak dolara musi znajdować się w nawiasach, aby wyrażenie działało? Spodziewałem ^(?!foo)$się dać te same wyniki, ale tak nie jest.
Grant Humphries,
3
@GrantHumphries: Gdy $kotwica znajduje się wewnątrz anteny, jest to część warunku, część tego stwierdzenia o zerowej szerokości . Gdyby znajdował się na zewnątrz, jak w ^(?!foo)$, będzie częścią wzorca konsumpcji wymagającego końca łańcucha zaraz po rozpoczęciu łańcucha, co sprawi, że negatywne spojrzenie w przód nie będzie miało znaczenia, ponieważ zawsze zwróci prawdę (nie może być tekstu po końcu łańcucha , nie mówiąc już foo). Tak więc ^(?!foo$)dopasowuje początek łańcucha, który nie jest śledzony foo, po którym następuje koniec łańcucha. ^(?!foo)$dopasowuje pusty ciąg.
Wiktor Stribiżew
@ robots.txt Usuń te komentarze. Zadajesz pytanie XY. Klasy postaci mają pasować do pojedynczych znaków, nie ma możliwości zdefiniowania z nimi sekwencji znaków. Prawdopodobnie powinieneś po prostu znaleźć podciąg między początkiem łańcucha a pierwszym wystąpieniem cotlub lani usunąć dopasowanie, jak regex.replace(myString, "^.*?(?:cot|lan)\s*", "").
Wiktor Stribiżew
Drogi Wiktorze. Zamknąłeś moje pytanie, jednak Twoja linkowana odpowiedź nie udaje się. Zaktualizowałem moje pytanie stackoverflow.com/questions/60004380/…
MonsterMMORPG
Na przykład linkowana odpowiedź kończy się niepowodzeniem w tym przykładzie „ing pakiety <! - i strona internetowa <! - asdasasdas -> teraz używają edytorzy -> Lorem Ipsum”
MonsterMMORPG
259

Możesz umieścić a ^na początku zestawu znaków, aby dopasować wszystko oprócz tych znaków.

[^=]*

dopasuje wszystko oprócz =

Firsh - LetsWP.io
źródło
55
To prawda, ale przetwarza tylko jedną postać na raz. Jeśli chcesz wykluczyć sekwencję dwóch lub więcej znaków, musisz użyć negatywnego spojrzenia w przód, tak jak mówili inni respondenci.
Alan Moore,
idealne rozwiązanie, aby usunąć wszelkie niepożądane postacie oprócz tych we wzorze. dzięki
Sirmyself
@Alan, „... musisz użyć negatywnego spojrzenia w przyszłość ...” jest niepoprawny, ale nie powinniśmy być dla ciebie zbyt surowi, ponieważ Wiktor nie opublikował swojej odpowiedzi - co pokazuje dlaczego - do 2016 r.
Cary Swoveland,
6

Po prostu dopasuj, /^index\.php/a następnie odrzuć wszystko, co pasuje.


źródło
Być może napisane str !~ /\Aindex\.php/.
Cary Swoveland,
6

W python:

>>> import re
>>> p='^(?!index\.php\?[0-9]+).*$'
>>> s1='index.php?12345'
>>> re.match(p,s1)
>>> s2='index.html?12345'
>>> re.match(p,s2)
<_sre.SRE_Match object at 0xb7d65fa8>
AJ
źródło
3
To odrzuci „index_php” lub „index # php”.
1

Potrzebuję regex stanie dopasować wszystko, ale except się ciąg rozpoczynający się od index.php określonego wzoru (konkretnie index.php a co za tym idzie, jak index.php? Id = 2342343)

Użyj metody Exec

    let match,
        arr = [],
        myRe = /([\s\S]+?)(?:index\.php\?id.+)/g;

    var str = 'http://regular-viragenia/index.php?id=2342343';

    while ((match = myRe.exec(str)) != null) {
         arr.push(match[1]);
    } 
    
    console.log(arr);

var myRe = /([\s\S]+?)(?:index\.php\?id=.+)/g;
var str = 'http://regular-viragenia/index.php?id=2342343';
var matches_array = myRe.exec(str);
console.log(matches_array[1]);

LUB INNE MECZE

let match,
            arr = [],
            myRe = /index.php\?id=((?:(?!index)[\s\S])*)/g;

        var str = 'http://regular-viragenia/index.php?id=2342343index.php?id=111index.php?id=222';

        while ((match = myRe.exec(str)) != null) {
             arr.push(match[1]);
        } 

        console.log(arr);

Юрий Светлов
źródło
-13

Może nie użyjesz wyrażenia regularnego:

// In PHP
0 !== strpos($string, 'index.php')
Percutio
źródło
11
OP specjalnie poprosił o wyrażenie regularne ... Nie jestem pewien, czy to pomaga! (Może używać np. grepW wierszu poleceń, Perl / Python / w dowolnym innym języku lub w poleceniu „Wykonaj wyrażenie regularne dla każdej linii” w edytorze tekstów itp.)
rinogo,