2017-05-26 3 views
1

J'essaie de capturer des mots constants dans une chaîne. Cette constante est:Qu'est-ce que regex peut capturer 2 mots exacts dans une phrase?

  1. un mot
  2. suivi par un séparateur (espaces, points, tiret ou underscore)
  3. un autre mot
  4. puis un séparateur (voir # 2) ou à la fin de la ligne ou de la chaîne.

Pour l'exemple de bien disons que je suis à la recherche de "Bob 1", dans les chaînes suivantes:

Hello, I'm Bob 1 --> Should capture Bob 1 
Hello, I'm Bob 11 --> Should capture nothing (Bob 1 is not at the end or followed by a separator) 
Hey, it's Bob-1 over there --> Should capture Bob-1 
Hey, it's Bob - 1 over there --> Should capture nothing (Bob should be followed only by one separator not 3 like here) 
Bob.1 --> Should capture Bob.1 
Bob_1 rules! --> Should capture Bob_1 

J'ai un regex qui fonctionne la plupart du temps:

/Bob[\s._-]1[\s._-]/ig 

En la deuxième liste je ne sais pas comment ajouter la fin de la chaîne dans les caractères possibles ... Qui se termine en seulement la dernière ligne dans la démo en direct ci-dessous qui devrait être une correspondance et ce n'est pas capturé. Voir le live demo.

J'utilise pcre (en PHP).

Répondre

1

Je ne suis pas en utilisant PHP, mais les matches suivants pour moi:

\bBob[\s.\-_]1\b 

Il fait usage de \b qui respecte une limite de mot. J'ai trouvé que je devais échapper à la ligne de commande à l'intérieur des crochets, ce qui n'est pas quelque chose que vous faites mais qui peut être une différence entre les moteurs regex que nous utilisons.

+0

Juste pour ajouter, que vous devez vérifier ce qui vient avant « Bob » parce que « Bob » pourrait faire partie d'une chaîne donc pourquoi j'ai inclus un \ b au début. –

+0

Je n'ai pas besoin d'y échapper dans mon exemple car c'est le dernier caractère de la liste. Si ce n'est pas le moteur pense que c'est une gamme de caractères et vous devez y échapper. – AlexV

0

Qui se termine uniquement par la dernière ligne de la démonstration en direct ci-dessous qui devrait correspondre et qui n'est pas capturée.

Pour cela vous avez besoin d'un lookahead positif.

Regex:Bob[\s._-]1(?=[\s._-])

  • (?=[\s._-]) ne regarderont pour la classe de caractères donner et ne correspondra pas à/capturer.

Regex101 Demo

0

Dans la deuxième liste, je ne sais pas comment ajouter la fin de la chaîne dans les caractères possibles.

Vous pouvez utiliser cette regex avec l'ancre $ pour affirmer la fin de chaîne:

/\bBob[\s._-]1(?:[\s._-]|$)/m 

ou si vous ne voulez pas correspondre à caractère suivant après le 2 mot puis utilisez un test avant:

/\bBob[\s._-]1(?=[\s._-]|$)/m 

([\s._-]|$) va affirmer la présence des caractères donnés (l'un des espaces, DOT, Underscore, trait d'union) ou la fin de la ligne $.

Il est plus sûr d'ajouter \b avant Bob pour correspondre mot exact Bob et éviter correspondant HelloBob

RegEx Demo

1

Cela fonctionne

https://regex101.com/r/ezikuP/2

(?<!\S)Bob[\s._-]1(?![^\s._-])

Formatted

(?<! \S)    # Whitespace boundary 
Bob      # Word 1 
[\s._-]     # Special seperator 
1      # Word 2 
(?! [^\s._-])   # Special seperator boundary