2010-02-07 4 views
18

Je suis perplexe en essayant de créer une expression régulière Emacs qui exclut les groupes. [^] exclut les caractères individuels d'un ensemble, mais je souhaite exclure des séquences spécifiques de caractères: quelque chose comme [^(not|this)], de sorte que les chaînes contenant "not" ou "this" ne correspondent pas.Comment écrire une expression régulière qui exclut plutôt que des correspondances, par exemple, pas (cette | chaîne)?

En principe, je pourrais écrire ([^n][^o][^t]|[^...]), mais y a-t-il une autre façon qui soit plus propre?

+3

Je pense que c'est GNU ERE. – Gumbo

+0

@Gumbo. vous avez raison, merci – Anycorn

+0

Cliquez sur le "regex-negation" tag pour voir des questions similaires. – finnw

Répondre

13

Tout d'abord: [^n][^o][^t] n'est pas une solution. Cela exclut également les mots comme nil ([^n] ne correspond pas), bob ([^o] ne correspond pas) ou cat ([^t] ne correspond pas).

Mais il est possible de construire une expression régulière avec la syntaxe de base qui fait des chaînes de match qui ne contiennent not ni this:

^([^nt]|n($|[^o]|o($|[^t]))|t($|[^h]|h($|[^i]|i($|[^s]))))*$ 

Le motif de cette expression régulière est de permettre à tout caractère pas la première caractère des mots ou seulement les préfixes des mots mais pas les mots entiers.

+12

+1, et si jamais j'étais tenté de passer à Emacs, ce serait une raison suffisante pour ne pas le faire. Comment quelqu'un peut * vivre * sans lookaheads? : P –

+1

J'ai beaucoup aimé Emacs jusqu'ici, c'est mon premier "ce que ..." – biocyberman

19

Ce n'est pas facile. Les expressions régulières sont conçues pour correspondre à choses, et c'est tout ce qu'elles peuvent faire.

Tout d'abord: [^] ne désigne pas un "groupe exclu", il désigne une classe de caractères niée. Les classes de caractères ne prennent en charge le regroupement sous aucune forme ou forme. Ils prennent en charge les caractères uniques (et, par commodité, les gammes de caractères). Votre essai [^(not|this)] est 100% équivalent à [^)(|hinots], en ce qui concerne le moteur regex.

Trois façons peuvent mener de cette situation:

  1. rencontres (not|this) et excluent les correspondances avec l'aide de l'environnement que vous êtes (annule les résultats match)
  2. utilisation négative look-ahead, si votre moteur de regex et réalisable dans la situation
  3. récrire l'expression de sorte qu'il peut match de: voir a similar question I asked earlier
+1

Je me demande pourquoi cette réponse est si basisée, c'est la réponse la plus claire ici! –

+0

@Yagamy Parce que ça dit plus ou moins "ça ne marche pas" alors qu'il y a clairement un moyen de le faire fonctionner (même si c'est un peu pratique qui est plus un dernier recours). – Tomalak

+1

Je ne vois pas ici une déclaration "Ne fonctionne pas", même contraire: vous avez montré trois façons qui pourraient résoudre le problème, et le troisième est juste comme la réponse acceptée. –

6

Essayez les lignes de vidange M-x.

13

Difficile à croire que la réponse acceptée (de Gumbo) a été acceptée! Sauf si elle a été acceptée, car il a indiqué que vous ne pouvez pas faire ce que vous voulez. À moins que vous n'ayez une fonction qui génère de telles regexps (comme le montre Gumbo), les composer serait une vraie douleur.

Quel est le cas d'utilisation réel - qu'est-ce que vous essayez vraiment de faire?

Comme Tomalak l'a indiqué, (a) ce n'est pas ce que font les expressions rationnelles; (b) voir l'autre poste auquel il est lié, pour une bonne explication, y compris ce qu'il faut faire à propos de votre problème.

La réponse est d'utiliser une expression rationnelle pour correspondre à ce que vous faites pas voulez, puis soustraire cela du domaine initial.IOW, n'essayez pas de faire de l'expression rationnelle l'exclusion (elle ne peut pas); faites l'exclusion après en utilisant une expression rationnelle pour correspondre à ce que vous voulez exclure.

Voici comment fonctionne chaque outil qui utilise des expressions rationnelles (par exemple, grep): elles offrent une option séparée (par exemple via la syntaxe) qui effectue la soustraction - après avoir fait correspondre ce qui doit être soustrait.

6

Il semble que vous essayiez de faire un lookahead négatif. c'est-à-dire que vous essayez d'arrêter de correspondre une fois que vous avez atteint un délimiteur.

Emacs ne prend pas en charge la fonction de recherche directe, mais il prend en charge la version non gourmande de *, + et? opérateurs (* ?, + ?, ??), qui peuvent être utilisés dans le même but dans la plupart des cas.

Ainsi, par exemple, pour correspondre au corps de cette fonction javascript:

bar = function (args) { 
    if (blah) { 
     foo(); 
    } 
}; 

Vous pouvez utiliser cette emacs regex:

function ([^)]+) {[[:ascii:]]+?}; 

Ici nous arrêter une fois que nous trouvons les deux séquences d'éléments "};" [[: ascii:]] est utilisé instad du "." opérateur car il fonctionne sur plusieurs lignes.

Ceci est un peu différent de lookahead négatif parce que le}; séquence elle-même correspondait, cependant si votre objectif est d'extraire tout jusqu'à ce point, vous utilisez simplement un groupe de capture \ (et \).

Voir le emacs manuel regex: http://www.gnu.org/software/emacs/manual/html_node/emacs/Regexps.html

Comme une note de côté, si vous écrire tout type de emacs regex, assurez-vous d'invoquer Mx re-constructeur, qui apportera un peu IDE pour écrire votre regex contre le tampon courant.

1

En cas d'alignement d'une chaîne pour test logique, je fais ceci:

;; Code to match string ends with '-region' but excludes those that has 'mouse'. 
M-x ielm RET 
*** Welcome to IELM *** Type (describe-mode) for help. 
ELISP> (setq str1 "mouse-drag-region" str2 "mou-drag-region" str3 "mou-region-drag") 
"mou-region-drag" 
ELISP> (and (string-match-p "-region$" str1) (not (string-match-p "mouse" str1))) 
nil 
ELISP> (and (string-match-p "-region$" str2) (not (string-match-p "mouse" str2))) 
t 
ELISP> (and (string-match-p "-region$" str3) (not (string-match-p "mouse" str3))) 
nil 

J'utilise cette approche pour éviter le bug de la fonction que je discutais Over Here:

Questions connexes