Regex соответствует только целым словам - PullRequest
73 голосов
/ 17 ноября 2009

У меня есть выражение регулярного выражения, которое я использую, чтобы найти все слова в данном блоке содержимого без учета регистра, которые содержатся в глоссарии, хранящемся в базе данных. Вот мой рисунок:

/($word)/i

Проблема в том, что если я использую /(Foo)/i, то такие слова, как Food, будут сопоставлены. С обеих сторон слова должен быть пробел или граница слова.

Как я могу изменить свое выражение, чтобы оно соответствовало только слову Foo, когда оно является словом в начале, середине или конце предложения?

Ответы [ 5 ]

97 голосов
/ 17 ноября 2009

Использовать границы слов:

/\b($word)\b/i

Или, если вы ищете "S.P.E.C.T.R.E." как в примере Синан Юнюр:

/(?:\W|^)(\Q$word\E)(?:\W|$)/i
36 голосов
/ 06 января 2014

Чтобы соответствовать любому целому слову, вы должны использовать шаблон (\w+)

Предполагается, что вы используете PCRE или что-то подобное:

enter image description here

Выше приведен скриншот из этого примера: http://regex101.com/r/cU5lC2

Совпадение любого целого слова в командной строке с (\w+)

Я буду использовать интерактивную оболочку phpsh в Ubuntu 12.10 , чтобы продемонстрировать механизм регулярных выражений PCRE с помощью метода, известного как preg_match

Запустите phpsh, поместите некоторый контент в переменную, сопоставьте по слову.

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

Метод preg_match использовал механизм PCRE в языке PHP для анализа переменных: $content1, $content2 и $content3 с шаблоном (\w)+.

$ content1 и $ content2 содержат хотя бы одно слово, а $ content3 - нет.

Совпадение количества буквенных слов в командной строке с (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

переменные gun1 и gun2 содержат строку dart или fart. gun4 нет. Однако может возникнуть проблема, что поиск слова fart соответствует farty. Чтобы исправить это, установите границы слов в регулярном выражении.

Сопоставлять буквенные слова в командной строке с границами слов.

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

То же самое, что и в предыдущем примере, за исключением того, что слово fart с границей слова \b не существует в содержимом: farty.

8 голосов
/ 17 ноября 2009

Использование \b может дать удивительные результаты. Было бы лучше выяснить, что отличает слово от его определения, и включить эту информацию в ваш шаблон.

#!/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";
}

Выход:

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"
1 голос
/ 07 июня 2018

использовать границы слов \ b,

Следующее (с использованием четырех escape) работает в моей среде: Mac, safari Версия 10.0.3 (12602.4.8)

var myReg = new RegExp(‘\\\\b’+ variable + ‘\\\\b’, ‘g’)
0 голосов
/ 11 июня 2019

Если вы делаете это в Notepad ++

[\w]+ 

Даст вам слово целиком, и вы можете добавить скобки, чтобы получить его как группу. Пример: conv1 = Conv2D(64, (3, 3), activation=LeakyReLU(alpha=a), padding='valid', kernel_initializer='he_normal')(inputs). Я хотел бы переместить LeakyReLU в свою строку в качестве комментария и заменить текущую активацию. В notepad ++ это можно сделать с помощью следующей команды find:

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

и команда замены становится:

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

Пробелы должны сохранять правильное форматирование в моем коде. :)

...