web-dev-qa-db-fra.com

Les expressions régulières 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é, insensibles à 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, des mots comme Food sont trouvés. Il doit y avoir des espaces ou une limite de Word des deux côtés de la Parole.

Comment modifier mon expression pour ne faire correspondre que le mot Foo lorsqu'il s'agit d'un mot au début, au milieu ou à la fin d'une phrase?

76
Aaron

Utilisez les limites de mot:

/\b($Word)\b/i

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

/(?:\W|^)(\Q$Word\E)(?:\W|$)/i
99
Richard Simões

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

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

enter image description here

Ci-dessus, capture d'écran prise de cet exemple en direct: http://regex101.com/r/cU5lC2

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

J'utiliserai le phpsh interactive Shell sur buntu 12.1 pour démontrer le moteur de regex PCRE par la méthode connue sous le nom preg_match

Lancez phpsh, mettez du contenu dans une variable, faites une correspondance sur Word.

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 a utilisé le moteur PCRE dans le langage PHP pour analyser les variables: $content1, $content2 et $content3 avec le (\w)+ modèle.

$ content1 et $ content2 contiennent au moins un mot, pas $ content3.

Faites correspondre un 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 le fait pas. Cependant, il peut être problématique que la recherche de Word fart corresponde à farty. Pour résoudre ce problème, appliquez les limites de Word dans regex.

Faites correspondre les mots littéraux sur la ligne de commande aux limites de Word.

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

Donc, c'est la même chose que dans l'exemple précédent, sauf que le mot fart avec un \b La limite de mot n'existe pas dans le contenu: farty.

36
Eric Leschinski

En utilisant \b peut donner des résultats surprenants. Vous feriez mieux de déterminer ce qui sépare 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:

 Compiler REx "\ b (S \. P\.E \. C\.T\.R\.E \.)\B" 
 Programme final: 
 1 : BOUND (2) 
 2: OPEN1 (4) 
 4: EXACT (9) 
 9: CLOSE1 (11) 
 11: BOUND (12) 
 12: END (0) 
 Ancré "SPECTRE" à 0 (vérification ancrée) stclass BOUND minlen 14 
 Deviner le début de la correspondance dans sv pour REx "\ b (S\.P\.E\.C\.T\.R\.E \.]\b "contre" SP 
. ECTRE (cadre spécial pour la contre-intelligence, ... ... 
 a trouvé un substrat ancré "SPECTRE" au décalage 0 ... 
 start_shift: 0 check_at : 0 s: 0 endpos: 1 
 Ne contredit pas STCLASS ... 
 Deviné: correspond au décalage 0 
 Correspondant à REx "\ b (S \. P\.E\\ .C\.T\.R\.E \.)\B "contre" SPECTRE (Special Exec 
 Utive for Contre-intelligence, "... 
 0 | 1: BOUND (2 ) 
 0 | 2: OPEN1 (4) 
 0 | 4: EXACT (9) 
 14 | 9: CLOSE1 (11) 
 14 | 11: BOUND (12) 
 A échoué ... 
 La correspondance a échoué 
 Libération de REx: "\ b (S \. P\.E \. C \. T\.R\.E \.)\b "
8
Sinan Ünür

utiliser les limites de mot\b,

Ce qui suit (en utilisant quatre échappements) fonctionne dans mon environnement: Mac, safari Version 10.0.3 (12602.4.8)

var myReg = new RegExp(‘\\\\b’+ variable + ‘\\\\b’, ‘g’)
1
X. L

Si vous le faites dans Notepad ++

[\w]+ 

Vous donnerait le mot entier, et vous pouvez ajouter une parenthèse pour l'obtenir en groupe. Exemple: conv1 = Conv2D(64, (3, 3), activation=LeakyReLU(alpha=a), padding='valid', kernel_initializer='he_normal')(inputs). Je voudrais déplacer LeakyReLU dans sa propre ligne en tant que commentaire et remplacer l'activation actuelle. Dans Notepad ++, cela peut être fait en utilisant la commande suivante:

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

et la commande de remplacement devient:

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

L'espace est de garder le bon formatage dans mon code. :)

0
JTIM