2008-10-02 10 views
78

J'utilise RegexBuddy mais je suis en difficulté de toute façon avec cette chose: \Comment "faire correspondre" avec regex?

Je suis en train de traiter ligne par ligne un fichier. J'ai construit un "modèle de ligne" pour correspondre à ce que je veux.

Maintenant, je voudrais faire une correspondance inverse ... à savoir que je veux faire correspondre les lignes où il y a une série de 6 lettres, mais seulement si ces six lettres sont pasAndrea, comment dois-je faire cette?


EDIT: Je vais écrire le programme qui utilise cette expression régulière, je ne sais pas encore si en python ou php, je fais cette chose tout d'abord apprendre quelques regex :) Il y a différents types de ligne, je voulais utiliser regex pour sélectionner le type qui m'intéresse. Une fois que j'ai obtenu ces lignes, je dois appliquer un autre filtre juste pour ne pas correspondre à une valeur connue, j'ai besoin de tous les autres, pas cette. Le (?! Non-voulu) fonctionne très bien, merci. :-)

J'espère que cela clarifie la question :)

+0

En fait, il semble que vous feriez mieux de nous donner un peu plus d'informations sur ce que vous faites, et voir si quelqu'un peut offrir une solution alternative.En règle générale, la tentative d'analyse d'un fichier entier en construisant une expression régulière qui correspond à chaque ligne est une route assez compliqué :) – Dan

Répondre

47
(?!Andrea).{6} 

En supposant que votre moteur regexp supporte lookaheads négatives ..

Edit: ..ou peut-être vous préféreriez utiliser [A-Za-z]{6} en place Edit (again): Notez que les lookaheads et les lookbehinds ne sont généralement pas la bonne façon d '"inverser" une correspondance d'expression régulière. Les expressions rationnelles ne sont pas vraiment configurées pour faire des correspondances négatives, elles laissent à n'importe quelle langue avec laquelle vous les utilisez.

+0

Vous devez ajouter le^que @Vinko Vrsalovic utilise pour qu'il ne correspond pas à sur « ndrea \ n » – bdukes

+2

. ne correspond pas à \ n par défaut (certaines langues [par exemple Perl] vous permettent d'activer ce comportement, mais par défaut, tout correspond à BUT \ n). – Dan

+1

(plus, l'OP n'a jamais mentionné que la chaîne devait se produire au début de la ligne) – Dan

5

Negative lookahead assertion

(?!Andrea) 

Ce n'est pas exactement une correspondance inversée, mais il est le meilleur que vous pouvez directement faire avec regex. Toutes les plateformes ne les supportent cependant pas.

+1

Jusqu'à ce que le questionneur clarifie, je ne vois pas que le match doit commencer au début de la ligne. Alors pourquoi le ^? –

+0

mish a parfaitement raison –

+0

Parce que j'ai compris qu'il voulait vérifier au début de la ligne, édité vu clarifications –

10

Quelle langue utilisez-vous? Les capacités et la syntaxe de l'implémentation de regex sont importantes pour cela.

Vous pouvez utiliser le mode anticipé. En utilisant python comme un exemple

import re 

not_andrea = re.compile('(?!Andrea)\w{6}', re.IGNORECASE) 

Pour briser ce bas:

(! Andrea) moyen de match si les 6 caractères suivants ne sont pas "Andrea" '; Si oui, alors

\ w signifie un "caractère de mot" - caractères alphanumériques. Ceci est équivalent à la classe [a-zA-Z0-9_]

\ w {6} signifie exactement 6 caractères de mot.

re.IGNORECASE signifie que vous exclure « Andrea », « andrea », « ANDREA » ...

Une autre façon est d'utiliser votre logique de programme - utiliser toutes les lignes qui ne correspondent pas Andrea et les mettre à travers une deuxième regex pour vérifier 6 caractères.Ou vérifiez d'abord les caractères d'au moins 6 mots, puis vérifiez qu'il ne correspond pas à Andrea.

-3

En Perl, vous pouvez faire

processus

(ligne de $) si (ligne $ = ~/Andrea /!);

+4

Cette syntaxe est fausse. Je pense que vous voulez dire le processus ($ line) si $ line! ~/Andrea/ – dland

4

Si vous voulez faire cela dans RegexBuddy, il y a deux façons d'obtenir une liste de toutes les lignes ne correspondant pas à une regex.

Dans la barre d'outils du panneau Test, définissez la portée de test sur "Ligne par ligne". Lorsque vous faites cela, un élément Liste toutes les lignes sans correspondances apparaîtra sous le bouton Lister tout dans la même barre d'outils. (Si vous ne voyez pas le bouton Lister tout, cliquez sur le bouton Faire correspondre dans la barre d'outils principale.)

Sur le panneau GREP, vous pouvez activer les cases à cocher "Ligne" et "Inverser les résultats" pour obtenir une liste de lignes qui ne correspondent pas dans les fichiers que vous parcourez.

40
+1

Aussi bien travaillé en ruby ​​pour moi, merci –

+0

Ne semble pas fonctionner dans 'stringi :: stri_match_all_regex' de R. – isomorphismes

+1

Cela ne fonctionne pas. Vous pensez à l'idiome Tempered Greedy Token. mais le point doit aller * après * l'aperçu, pas avant. Voir [cette question] (http://stackoverflow.com/questions/30900794/tempered-greedy-token-what-is-different-about-placing-the-dot-before-the-negat). Mais cette approche est trop lourde pour cette tâche de toute façon. –

3

(?! est utile dans la pratique. Bien que strictement parlant, regarder vers l'avenir n'est pas une expression régulière telle que définie mathématiquement.

Vous pouvez écrire une expression régulière inversée manuellement.

Pour calculer automatiquement le résultat. Son résultat est généré par la machine, ce qui est généralement beaucoup plus complexe que l'écriture manuelle. Mais le résultat fonctionne.

10

mis à jour avec les commentaires de Alan Moore

En PCRE et des variantes similaires, vous pouvez réellement créer une expression régulière qui correspond à une ligne ne contenant pas une valeur:

^(?:(?!Andrea).)*$ 

Ceci est appelé tempered greedy token. L'inconvénient est qu'il ne fonctionne pas bien.

+1

Ceci est le jeton gourmand tempéré en forme longue. Mettez juste le point (ou '[\ s \ S]', qui n'est utile qu'en JavaScript) après le second lookahead, et vous n'avez pas besoin du premier: '^ (? :(?! Andrea).) * $ '. –

+0

@AlanMoore Nice! Je n'ai pas trouvé de modèle établi qui fonctionne comme ça, alors j'ai inventé le mien. Plutôt que de me prendre votre réponse, vous devriez la fournir comme la vôtre. – Zenexer

+0

C'est bon, il y a déjà beaucoup de bonnes réponses. Et vous méritez le crédit pour avoir inventé l'idiome par vous-même. À votre santé! –

0

Je suis venu avec cette méthode qui peut être matériel intensif mais il travaille:

Vous pouvez remplacer tous les caractères qui correspondent à l'expression rationnelle par une chaîne vide.

C'est un oneliner:

notMatched = re.sub(regex, "", string)

je parce que je suis obligé d'utiliser un regex très complexe et ne pouvait pas comprendre comment inverser chaque partie. Cela ne vous retournera que le résultat de la chaîne, pas d'objets correspondants!

Questions connexes