8
votes

Correspondant exactement à une occurrence dans une chaîne avec une expression régulière

L'autre jour, je me suis assis avec un problème d'expression régulier. Finalement, j'ai résolu une manière différente, sans expressions régulières, mais j'aimerais toujours savoir comment vous le faites :)

Le problème que j'avais eu était exécuté à la mise à jour SVN via un script automatisé et je voulais détecter les conflits. Faire cela avec ou sans regex est trivial, mais cela m'a fait penser à un problème plus obscur: comment correspondre-tu exactement à une occurrence d'un caractère à l'intérieur d'un champ de longueur fixe de blancheur?

Par exemple, disons Nous voulions faire correspondre "C" à l'intérieur d'un champ large de six octets: xxx


0 commentaires

3 Réponses :


5
votes
^             # start-of-string
(?=[ C]{6}$)  # followed by exactly 6 times " " or "C" and the end-of-string
 *C           # any number of spaces and a "C"
(?! *C)       # not followed by another C anywhere (negative lookahead)

4 commentaires

Il ne devrait pas être ^ C, l'utilisateur a demandé un espace blanc.


+1 pour une utilisation géniale de lookaheads, exemple intéressant. Cependant, le match échoue sur deux occurrences de C, cela le fixe: ^ (? =. {6} $) [^ c] *? C (? * C)


sur 2e inspection, cela échoue lorsque c est mélangé avec d'autres caractères


@Kennethj: Je viens de changer la regex pour répondre à cela.



4
votes
^[^C]*C[^C]*$
but this will not verify the length of your string.

9 commentaires

+1 Les classes de caractères négatifs sont meilleures que mes lookaheads.


Les classes de caractères sont meilleures. Mais cela ne prend pas en compte la longueur totale. Donc, vous devrez faire quelque chose comme: ^ (c [^ c] {5} | [^ c] c [^ c] {4} | [^ c] {2} c [^ c] {3 } | [^ C] {3} c [^ c] {2} | [^ c] {4} c [^ c] {5} c) $


... mais malheureusement, avec la deuxième exigence (espaces uniquement), cela ne fonctionne plus. Voir le commentaire de Testalino sur ma réponse.


Résolu, vous devez incorporer la Longueur Lookahead de Tomalak et remplacer [^ c] * avec WhitSpace: ^ (? =. {6} $) * C * $


@Gumbo: Vous n'êtes pas sérieux. Je doute que cela battrait des looks dans la performance.


@Tomalak: Peut-être pas celui-là. Mais peut-être que celui-ci: ^ (c [^ c] {5} | [^ c] (c [^ c] {4} | [^ c] (c [^ c] {3} | [^ C] ] (C [^ c] {2} | [^ c] (c [^ c] | [^ c] c))))) $ ;)


@Tomalak: Le point est plutôt que toutes les implémentations d'expression régulière ne soutiennent pas les assertions des points de vue.


@Gumbo, si ce n'est pas la mise en œuvre de chaque reine prend en charge les points de vue, alors chaque implémentation prend en charge la longueur d'une chaîne. Donc, juste à côté de la correspondance ...


@eumiro: Nous ne savons pas si toute la chaîne est toujours le sujet. Peut-être que c'est juste une sous-chaîne.



8
votes

Je sais que ce n'est pas raison de répondre à votre propre question, mais j'ai fondamentalement fusionné vos réponses ... s'il vous plaît ne flânez pas :)

^ (? =. {6} $) * C * $

EDIT: Remplacer. avec la réponse de Tomalak ci-dessous [C] augmente la vitesse avec environ 4-5% ou donc

^ (? = [c] {6} $) * C * $


9 commentaires

+1 Ouais, c'est bien aussi. La finale $ est toujours inutile, voir ma note n ° 2. (et non, il y a de mal à répondre à votre propre question. Pas de danger d'être flammé.)


@tomalak Si je retire la finale $, il échoue lorsque quelque chose d'autre que C se présente après le C, et aussi sur plusieurs occurrences de C


Consultez ma réponse modifiée pour un premier look-devant qui la corrige.


Je viens de faire du benchmarking, c'est de loin la variante la plus rapide: ^ (? = [C] {6} $) * C * . Un peu plus lent est la version basée sur la lecture à partir de ma réponse ^ (? = [C] {6} $) * C (?! * c) et @ Les deux fèges de monstres de Gumbo sont de la Les commentaires sur la réponse de @ Eumiro sont les plus lents du groupe, le second légèrement plus rapide que le premier.


@Tomalak - Avez-vous utilisé des espaces au lieu de [^ c] sur la regex de gumbo? Pendant que nous étions stupides, vous pourriez aussi bien tester c ----- | -c ---- | --c --- | --- C- | ---- C- | ----- C .


@tomalek Votre variante modifiée échoue toujours sur deux occurrences de C. Faites-la face, autant que vous ne voudriez pas ne pas l'avoir, vous avez besoin de la fin de $ :)


@Kenneth: Ouais, tu as raison, c'est vrai pour cette regex. Ce n'est pas vrai pour le mien, cependant.


@Kobi: Oui, j'ai utilisé des espaces au lieu de [^ c] .


@Kennethj Bien sûr, il a raison de répondez à votre propre question ! :)