2009-09-08 6 views
74

L'expression régulière peut-elle être utilisée pour correspondre à n'importe quelle chaîne sauf une constante de chaîne spécifique disons "ABC"? Est-ce possible d'exclure une seule chaîne spécifique? Merci d'avance pour votre aide.RegEx pour exclure une constante de chaîne spécifique

+1

Quel outil êtes-vous en utilisant? Selon l'outil, il pourrait y avoir un moyen de spécifier cet externe à votre regex. grep supporte une option -v pour inverser le sens de la correspondance, par exemple. –

+1

Vous ne pouvez pas juste 'si (/^ABC $ /) else {...} où l'autre serait l'ABC ne correspondant pas – Xetius

+0

Alors cherchez-vous à correspondre à tous les caractères d'une chaîne donnée, sauf la partie ABC de celui-ci ? En d'autres termes, "Une chaîne avec ABC" correspondrait à "Une chaîne avec". –

Répondre

4

Ce n'est pas facile, sauf si votre moteur d'expressions rationnelles a un support spécial. La façon la plus simple serait d'utiliser une option match négative, par exemple:

$var !~ /^foo$/ 
    or die "too much foo"; 

Sinon, vous devez faire quelque chose mal:

$var =~ /^(($)|([^f].*)|(f[^o].*)|(fo[^o].*)|(foo.+))$/ 
    or die "too much foo"; 

Que l'on dit en gros « si elle commence par non - f, le reste peut être n'importe quoi, s'il commence par f, non o, le reste peut être n'importe quoi, sinon, s'il commence fo, le prochain caractère ferait mieux de ne pas être un autre o ".

+0

Cela ne permettra pas la chaîne vide, 'f',' fo' et 'foo'. – Gumbo

+0

@Gumbo: Il permet la chaîne vide très bien; remarquez que ($) est la première alternative, donc^$ (chaîne vide) est acceptée. Je l'ai testé, et au moins dans perl 5.0.10 la chaîne vide est acceptée. – derobert

+0

... Désolé, perl 5.10.0, bien sûr! – derobert

93

Vous devez utiliser une assertion Lookahead négative.

(?!^ABC$) 

Vous pouvez par exemple utiliser ce qui suit.

(?!^ABC$)(^.*$) 

Si cela ne fonctionne pas dans votre éditeur, essayez ceci. Il est testé pour fonctionner en rubis et javascript:

^((?!ABC).)*$ 
+1

Cela fonctionnera si vous recherchez une chaîne qui n'inclut pas ABC. Mais est-ce le but? Ou est le but de correspondre à tous les caractères sauf ABC? –

+0

Merci d'avoir signalé cela, vous avez raison - ma suggestion évite seulement les chaînes commençant par ABC - j'ai oublié d'ancrer l'assertion. Je vais corriger cela. –

+0

C'est encore différent de ce que je pensais. Peut-être que l'intervenant clarifiera ce qu'il cherche. –

3

Vous pouvez utiliser préanalyse négative, ou quelque chose comme ceci:

^([^A]|A([^B]|B([^C]|$)|$)|$).*$ 

Peut-être que cela pourrait être un peu simplifié.

3

Dans .NET, vous pouvez utiliser le regroupement à votre avantage comme celui-ci:

http://regexhero.net/tester/?id=65b32601-2326-4ece-912b-6dcefd883f31

Vous remarquerez que:

(ABC)|(.) 

saisira tout sauf ABC dans le 2ème groupe. Les parenthèses entourent chaque groupe. Alors (ABC) est un groupe 1 et groupe 2.

Alors vous prenez juste le 2ème groupe comme celui-ci dans une remplacer (.):

$2 

Ou dans le regard .NET à la collection Groupes à l'intérieur du Classe Regex pour un peu plus de contrôle.

Vous devriez être capable de faire quelque chose de similaire dans la plupart des autres implémentations regex.

MISE À JOUR: J'ai trouvé un moyen beaucoup plus rapide de le faire ici: http://regexhero.net/tester/?id=997ce4a2-878c-41f2-9d28-34e0c5080e03

Il utilise encore le regroupement (je ne peux pas trouver un moyen qui n'utilise pas le regroupement). Mais cette méthode est plus de 10 fois plus rapide que la première.

2

Essayez cette expression régulière:

^(.{0,2}|([^A]..|A[^B].|AB[^C])|.{4,})$ 

Il décrit trois cas:

  1. moins de trois caractères arbitraires
  2. exactement trois caractères, alors que ce soit
    • le premier n'est pas A ou
    • le premier est A mais le second n'est pas B, ou
    • le premier est A, la deuxième B mais le troisième n'est pas C
  3. plus de trois caractères arbitraires
Questions connexes