2009-05-04 9 views
1

Avant de poser cette question, j'ai recherché Google pour ce problème et j'ai parcouru toutes les questions relatives à StackOverflow.C# regex ne correspond qu'à des parties de mots complets dans une chaîne

Le problème est assez simple

j'ai une chaîne "Organisation du Traité de l'Atlantique Nord"

J'ai un modèle "a. * Z", au moment où il égalerait

nord TRAITÉ ATLATIC orgaNisatioN

Mais je en ai besoin pour correspondre à des mots complets seulement (par exemple) orgaNisatioN

J'ai essayé « \ ba z \ b "et" \ Ba z \ B "comme motif, mais je pense que je ne comprends pas tout à fait

Comment devrais-je modifier mon motif afin de faire correspondre les mots complets que contient la chaîne (sans correspondance multiple mots)

Les motifs sont générés à la volée, l'utilisateur saisit un * z et mon application le traduit en motif qui correspond à des parties de mots complets dans une chaîne.

Mon problème est que je ne sais pas quel utilisateur va chercher. Idéalement, je devrais présenter une expression rationnelle à l'expression de l'utilisateur.

Merci!

+0

Les solutions actuelles sont excellentes, mais elles nécessitent une analyse syntaxique des chaînes, je suis à la recherche d'une solution de type prepent/append string. Je vous remercie. –

Répondre

4

ANIZ dans orgANIZation est pas un mot complet - c'est une partie d'un mot. Votre motif btw n'est pas ce que vous avez écrit - a*z ne correspond pas à ce que vous décrivez; vous utilisez probablement a.*z à la place, ce qui serait le cas. Donc, essayez a[^ ]*z pour qu'il ne corresponde pas aux espaces. S'il y a d'autres caractères que des espaces que vous ne voulez pas faire correspondre, par ex. certains types de ponctuation, les coller dans la construction [^...], bien sûr, bien sûr.

+0

Vous avez raison. S'il vous plaît regarder mon edit ... Merci :) –

3
"a[^\s]*z" 

Ceci signifie un 'a' suivi d'un nombre quelconque de caractères non-espaces, suivi d'un 'z'.

EDIT: Vous semblez vouloir que '*' soit interprété comme un caractère générique. L'utilisateur ne doit donc pas entrer une regex, mais une chaîne avec certains caractères génériques. Vous pouvez traduire ces caractères génériques en regex en raisonnant sur la signification voulue. Disons que '*' devrait signifier "zéro ou plusieurs caractères qui ne sont pas des espaces". Vous remplacez ce caractère, puis, avec la regex correspondante:

 
         [^\s]* 
         `-.-´| 
    Character class-----´ `---Zero or more of these 

    '\s': "Whitespace" 
    Inside Character class: if it starts with '^': "not" 

Vous pouvez également définir '?' comme correspondant exactement à un seul caractère non-espace. C'est la même classe de caractères, mais vous omettez le '*' à la fin.

Alors, ce que vous faites est-regex remplacer "*" par "[^\s]*" et "?" avec "[^\s]".

+0

S'il vous plaît regarder mon edit..Thank –

1

qui est ce que vous cherchez:

new Regex(@"\b[^ ]*a[^ ]*z[^ ]*\b"); 

il ne correspond qu'à un seul mot (sans espaces sont autorisés) - mais l'ensemble un.Vous pouvez traduire la saisie de vos utilisateurs dans une telle regex - il suffit de remplacer * par [^] * - cela fonctionne même avec plus d'un caractère générique.

1

Sans lien direct avec votre question, mais vous voudrez peut-être consulter un outil de visualisation RegEx qui vous montre les résultats caputrés basés sur la saisie de texte et une expression régulière donnée.

Un tel outil est très utile pour trouver le bon motif, ce qui peut être assez compliqué. Un bel outil spécialisé pour .net RegEx est RegExLab, un peu plus ancien mais fait un bon travail en montrant ce que votre expression régulière correspond exactement. Puisque la page est en allemand, cliquez simplement sur le lien regexlab.006.zip. Le code source est également inclus.

+0

J'utilise http://regexplib.com/RETester.aspx, mais votre outil est plus facile à utiliser. Je vous remercie. –

1
Regex reWord = new Regex("\\b[A-Za-z]*?(a.*z)[A-Za-z]*\\b"); 

... cela retournera "Organisation du Traité de l'Atlantique", avec la capture de a. * z étant "Antic Treaty Organiz".

Le problème est inhérent à votre méthode - à moins que vous analysez par modifing * à [^ \ s] * l'utilisateur fourni « regex » d'un * z (ou un * z, ce n'est pas tout à fait clair à partir de votre poste.) ? Comme le suggère Svante (ou peut-être \ w *?), vous allez engloutir beaucoup plus de personnages que vous le souhaitez.

". *" est, en général, une mauvaise idée lorsque vous essayez d'être spécifique. Cela va tout sauf un retour à la ligne, et il n'y a rien que vous pouvez ajouter à cela qui va arrêter cela.

Regex reWord = new Regex("\\b\\w*?(a\\w*?z)\\w*\\b"); 

... retournera simplement "Organisation". Sinon, si vous devez absolument, pour une raison quelconque, évitez de modifier l'expression rationnelle fournie par l'utilisateur, essayez peut-être de scinder vos chaînes en une série de mots et testez chaque mot individuellement par rapport à l'expression régulière.

En fin de compte, c'est GIGO - garbage in, garbage out. Nourrissez votre système d'une mauvaise regex et si vous ne le réparez pas correctement, vous n'obtiendrez pas ce que vous cherchez.

Questions connexes