157 votes

Les expressions rationnelles ne correspondent qu'à des mots entiers

J'ai une expression regex que j'utilise pour trouver tous les mots d'un bloc de contenu donné, sans tenir compte de la casse, qui sont contenus dans un glossaire stocké dans une base de données. Voici mon modèle :

/($word)/i

Le problème est que si j'utilise /(Foo)/i alors des mots comme Food être appariés. Il doit y avoir un espace blanc ou une limite de mot de part et d'autre du mot.

Comment puis-je modifier mon expression pour qu'elle corresponde uniquement au mot Foo lorsqu'il s'agit d'un mot au début, au milieu ou à la fin d'une phrase ?

212voto

Richard Simões Points 4981

Utilisez des limites de mots :

/\b($word)\b/i

Ou si vous cherchez "S.P.E.C.T.R.E.", comme dans l'exemple de Sinan Ünür :

/(?:\W|^)(\Q$word\E)(?:\W|$)/i

88voto

Eric Leschinski Points 14289

Pour faire correspondre un mot entier, vous devez utiliser le modèle suivant (\w+)

En supposant que vous utilisiez PCRE ou quelque chose de similaire :

enter image description here

La capture d'écran ci-dessus est tirée de cet exemple concret : https://regex101.com/r/FGheKd/1

Faire correspondre n'importe quel mot entier de la ligne de commande avec (\w+)

J'utiliserai le shell interactif phpsh en Ubuntu 12.10 pour démontrer l'efficacité de la Moteur regex PCRE par le biais de la méthode connue sous le nom de preg_match

Lancez phpsh, mettez du contenu dans une variable, faites correspondre les mots.

el@apollo:~/foo$ phpsh

php> $content1 = 'badger'
php> $content2 = '1234'
php> $content3 = '$%^&'

php> echo preg_match('(\w+)', $content1);
1

php> echo preg_match('(\w+)', $content2);
1

php> echo preg_match('(\w+)', $content3);
0

La méthode preg_match utilise le moteur PCRE du langage PHP pour analyser les variables : $content1 , $content2 y $content3 avec le (\w)+ modèle.

$content1 et $content2 contiennent au moins un mot, $content3 n'en contient pas.

Faire correspondre un certain nombre de mots littéraux sur la ligne de commande avec (dart|fart)

el@apollo:~/foo$ phpsh

php> $gun1 = 'dart gun';
php> $gun2 = 'fart gun';
php> $gun3 = 'farty gun';
php> $gun4 = 'unicorn gun';

php> echo preg_match('(dart|fart)', $gun1);
1

php> echo preg_match('(dart|fart)', $gun2);
1

php> echo preg_match('(dart|fart)', $gun3);
1

php> echo preg_match('(dart|fart)', $gun4);
0

Les variables gun1 et gun2 contiennent la chaîne dart ou fart. gun4 ne la contient pas. Toutefois, il se peut que le fait de rechercher le mot fart correspondances farty . Pour remédier à ce problème, il convient d'imposer des limites de mots dans les expressions rationnelles.

Faire correspondre les mots littéraux de la ligne de commande avec les limites des mots.

el@apollo:~/foo$ phpsh

php> $gun1 = 'dart gun';
php> $gun2 = 'fart gun';
php> $gun3 = 'farty gun';
php> $gun4 = 'unicorn gun';

php> echo preg_match('(\bdart\b|\bfart\b)', $gun1);
1

php> echo preg_match('(\bdart\b|\bfart\b)', $gun2);
1

php> echo preg_match('(\bdart\b|\bfart\b)', $gun3);
0

php> echo preg_match('(\bdart\b|\bfart\b)', $gun4);
0

C'est donc la même chose que dans l'exemple précédent, sauf que le mot fart avec un \b le mot frontière n'existe pas dans le contenu : farty .

11voto

Sinan Ünür Points 76179

Utilisation \b peut donner des résultats surprenants. Il est préférable de déterminer ce qui différencie un mot de sa définition et d'intégrer cette information dans votre modèle.

#!/usr/bin/perl

use strict; use warnings;

use re 'debug';

my $str = 'S.P.E.C.T.R.E. (Special Executive for Counter-intelligence,
Terrorism, Revenge and Extortion) is a fictional global terrorist
organisation';

my $word = 'S.P.E.C.T.R.E.';

if ( $str =~ /\b(\Q$word\E)\b/ ) {
    print $1, "\n";
}

Sortie :

Compiling REx "\\b(S\\.P\\.E\\.C\\.T\\.R\\.E\\.)\\b"
Final program:
   1: BOUND (2)
   2: OPEN1 (4)
   4:   EXACT  (9)
   9: CLOSE1 (11)
  11: BOUND (12)
  12: END (0)
anchored "S.P.E.C.T.R.E." at 0 (checking anchored) stclass BOUND minlen 14
Guessing start of match in sv for REx "\\b(S\\.P\\.E\\.C\\.T\\.R\\.E\\.)\\b" against "S.P
.E.C.T.R.E. (Special Executive for Counter-intelligence,"...
Found anchored substr "S.P.E.C.T.R.E." at offset 0...
start\_shift: 0 check\_at: 0 s: 0 endpos: 1
Does not contradict STCLASS...
Guessed: match at offset 0
Matching REx "\\b(S\\.P\\.E\\.C\\.T\\.R\\.E\\.)\\b" against "S.P.E.C.T.R.E. (Special Exec
utive for Counter-intelligence,"...
   0           |  1:BOUND(2)
   0           |  2:OPEN1(4)
   0           |  4:EXACT (9)
  14      |  9:CLOSE1(11)
  14      | 11:BOUND(12)
                                  failed...
Match failed
Freeing REx: "\\b(S\\.P\\.E\\.C\\.T\\.R\\.E\\.)\\b"

8voto

Pour ceux qui veulent valider un Enum dans leur code, vous pouvez suivre le guide suivant

Dans Regex World, vous pouvez utiliser ^ pour démarrer une chaîne de caractères et $ pour y mettre fin. En les utilisant en combinaison avec | pourrait être ce que vous voulez :

^(Male)$|^(Female)$

Il ne renverra un résultat positif que pour Male o Female cas.

3voto

JTIM Points 331

Si vous le faites dans Notepad++

[\w]+ 

Vous obtiendrez le mot entier, et vous pouvez ajouter des parenthèses pour l'obtenir en tant que groupe. Exemple : conv1 = Conv2D(64, (3, 3), activation=LeakyReLU(alpha=a), padding='valid', kernel_initializer='he_normal')(inputs) . Je souhaite déménager LeakyReLU dans sa propre ligne en tant que commentaire, et remplace l'activation actuelle. Dans Notepad++, cette opération peut être effectuée à l'aide de la commande "follow find" :

([\w]+)( = .+)(LeakyReLU.alpha=a.)(.+)

et la commande replace devient :

\1\2'relu'\4 \n    # \1 = LeakyReLU\(alpha=a\)\(\1\)

Les espaces permettent de conserver le bon formatage dans mon code :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X