Regex: correspond à tout sauf à un motif spécifique


310

J'ai besoin d'une expression régulière capable de tout faire correspondre, sauf une chaîne commençant par un modèle spécifique (spécifiquement index.phpet ce qui suit, comme index.php?id=2342343)


Et quel modèle spécifique voulez-vous ne pas faire correspondre?
Dominic Rodger

2
Y a-t-il une raison pour laquelle vous ne pouvez pas faire de correspondance avec votre modèle et ne pas faire quelque chose si la chaîne correspond à cela?
Thomas Owens


@ThomasOwens: Cela dépend. Cela dépend de quelle partie de l'expression doit être annulée. Si l'expression entière doit être niée, alors vous avez un point. Par exemple, si vous voulez coder "si la chaîne ne contient pas 'Bruce' comme sous-chaîne, alors faites quelque chose", vous utiliserez simplement / Bruce /, et placerez la négation dans l'instruction if, en dehors de l'expression régulière . Mais il se pourrait que vous souhaitiez annuler une sous-expression. Dites, vous recherchez quelque chose comme prénom nom de famille, où le prénom est Bruce, et le nom de famille est tout sauf XYZ, où XYZ est le nom de famille d'une célébrité appelée Bruce.
mathheadinclouds

Réponses:


250

Pas un expert en regexp, mais je pense que vous pouvez utiliser un lookahead négatif dès le début, par exemple ^(?!foo).*$ne devrait pas correspondre à quoi que ce soit commençant par foo.


7
Avec grep, utilisez -P pour activer l'anticipation.
Seppo Enarvi

Si ne correspond pas à "foo" ou "bar" est votre comportement souhaité, vérifiez cette réponse: stackoverflow.com/a/2404330/874824
dave_k_smith

15
Cette réponse est fausse, un test rapide le montre. Je pense que vous vouliez dire ^((?!foo).)*$( stackoverflow.com/a/406408/3964381 )
gilad mayani

4
Pouvez-vous expliquer les symboles que vous avez utilisés et pourquoi vous les avez utilisés?
rotimi-best

339

Regex: correspond à tout, mais :

Remarque sur la démo : la nouvelle ligne \nest utilisée à l'intérieur des classes de caractères annulées dans les démos pour éviter un débordement de correspondance avec la ou les lignes voisines. Ils ne sont pas nécessaires lors du test de chaînes individuelles.

Note d'ancrage : dans de nombreuses langues, utilisez \Apour définir le début de la chaîne sans ambiguïté et \z(en Python, c'est \Z, en JavaScript, $c'est OK) pour définir la fin de la chaîne.

Remarque : dans de nombreuses versions (mais pas POSIX, TRE, TCL), .correspond à n'importe quel caractère, à l'exception d' un caractère de nouvelle ligne . Assurez-vous d'utiliser un modificateur DOTALL correspondant ( /sdans PCRE / Boost / .NET / Python / Java et /mdans Ruby) pour .correspondre à n'importe quel caractère, y compris une nouvelle ligne.

Remarque\n sur les barres obliques inverses : dans les langues où vous devez déclarer des modèles avec des chaînes C permettant des séquences d'échappement (comme pour une nouvelle ligne), vous devez doubler les barres obliques inverses qui échappent aux caractères spéciaux afin que le moteur puisse les traiter comme des caractères littéraux (par exemple en Java, world\.sera déclaré en tant que "world\\.", ou utilisez une classe de caractères:) "world[.]". Utilisez des littéraux de chaîne bruts (Python r'\bworld\b'), des littéraux de chaîne verbatim C # @"world\."ou des notations littérales de chaînes slashy / regex comme /world\./.


Grande écriture! Dans le cas d'une "chaîne (non) égale à une chaîne", avec l'exemple de ^(?!foo$), pourquoi le signe dollar doit-il être entre parenthèses pour que l'expression fonctionne? Je m'attendais ^(?!foo)$à donner les mêmes résultats, mais ce n'est pas le cas.
Grant Humphries du

3
@GrantHumphries: lorsque l' $ancre est à l'intérieur de l'antichambre, elle fait partie de la condition, de cette assertion de largeur nulle . S'il était à l'extérieur, comme dans ^(?!foo)$, il fera partie du modèle de consommation nécessitant la fin de la chaîne juste après le début de la chaîne, ce qui rendrait l'anticipation négative non pertinente car elle retournerait toujours vrai (il ne peut y avoir de texte après la fin de la chaîne , encore moins foo). Ainsi, ^(?!foo$)correspond au début d'une chaîne qui n'est pas suivie par foocelle qui est suivie par la fin de la chaîne. ^(?!foo)$correspond à une chaîne vide.
Wiktor Stribiżew

@ robots.txt Veuillez supprimer ces commentaires. Vous posez une question XY. Les classes de caractères sont censées correspondre à des caractères uniques, il n'y a aucun moyen de définir une séquence de caractères avec eux. Vous devriez probablement trouver la sous-chaîne entre le début d'une chaîne et la première occurrence de cotor lan, et supprimer la correspondance, comme regex.replace(myString, "^.*?(?:cot|lan)\s*", "").
Wiktor Stribiżew

Cher Wiktor. Vous avez fermé ma question mais votre réponse liée échoue. J'ai mis à jour ma question stackoverflow.com/questions/60004380/…
MonsterMMORPG

Par exemple, votre réponse liée échoue dans cet exemple "ing packages <! - et la page Web <! - asdasasdas -> les éditeurs utilisent maintenant -> Lorem Ipsum"
MonsterMMORPG

259

Vous pouvez mettre un ^au début d'un jeu de caractères pour correspondre à tout sauf à ces caractères.

[^=]*

correspondra à tout, mais =


55
C'est vrai, mais il ne traite qu'un caractère à la fois. Si vous souhaitez exclure une séquence de deux ou plusieurs caractères, vous devez utiliser l'anticipation négative comme l'ont dit les autres répondants.
Alan Moore

solution parfaite pour supprimer tous les caractères indésirables, sauf ceux du motif. merci
Sirmyself

@Alan, "... vous devez utiliser une anticipation négative ..." est incorrect, mais nous ne devrions pas être trop durs avec vous parce que Wiktor n'a pas posté sa réponse - ce qui montre pourquoi - jusqu'en 2016.
Cary Swoveland

6

Faites simplement correspondre /^index\.php/puis rejetez ce qui correspond.


Peut-être écrit str !~ /\Aindex\.php/.
Cary Swoveland

6

En 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>

3
Cela rejettera "index_php" ou "index # php".

1

Je besoin d' un regex capable de correspondre à tout , mais excepter une chaîne commençant par index.php un motif spécifique ( en particulier index.php et ce qui suit, comme index.php? Id = 2342343)

Utiliser la méthode 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]);

OU AUTRE MATCH

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);


-13

Que diriez-vous de ne pas utiliser regex:

// In PHP
0 !== strpos($string, 'index.php')

11
L'OP a spécifiquement demandé une expression régulière ... Je ne suis pas sûr que cela aide! (Il peut utiliser grepsur la ligne de commande, par exemple, ou Perl / Python / tout autre langage, ou une commande "Exécuter cette expression régulière pour chaque ligne" dans un éditeur de texte, etc ...)
rinogo
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.