Regex відповідає лише цілим словам


90

У мене є вираз регулярного виразу, який я використовую, щоб знайти всі слова в даному блоці вмісту, не враховуючи регістр, які містяться в глосарії, що зберігається в базі даних. Ось моя схема:

/($word)/i

Проблема полягає в тому, що якщо я використовую /(Foo)/iтакі слова, як Foodотримати відповідність. По обидва боки слова має бути пробіл або межа слова.

Як я можу змінити свій вираз, щоб він відповідав лише слову, Fooколи це слово на початку, в середині або в кінці речення?

Відповіді:


120

Використовуйте межі слів:

/\b($word)\b/i

Або якщо ви шукаєте "СПЕКТР", як у прикладі Сінана Унура:

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

1
Я просто набирав довгу версію цієї відповіді, коли ви розміщували повідомлення. :)
ZombieSheep

@RichardSimoes \b(<|>=)\bне збігається>=
alhelal

@RichardSimoes та \b[-|+][0-9]+\bматч +10у 43E+10. І того, і іншого я не хочу.
alhelal

що якщо я хочу шукати слово, яке не додається або не міститься в жодному іншому слові. тоді ця логіка не спрацює
Прасанна Сасне

Як би хтось отримав математичні оператори порівняння> = і <=?
AntonSack

50

Для відповідності будь-якому цілому слову ви використовували б шаблон (\w+)

Припускаючи, що ви використовуєте PCRE або щось подібне:

введіть тут опис зображення

Знімок екрана, зроблений із цього реального прикладу: 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.


am, pm - це не слова?
міньйон

Якщо ви хочете змусити am та pm бути словами (вони не є, вони є абревіатурами), тоді додайте крапку як символ слова для вашого механізму регулярних виразів. Для вас, здається, ви встановили крапку не як символ слова, тому слова регулярних виразів не будуть однозначними та стандартними для визначення слова "слово", якому вас навчили у вашому європейському словнику для вашого гібридного європейського мова (або будь-яка інша мова).
Ерік Лещинський

8

Використання \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";
}

Вихід:

Компіляція REx "\ b (S \ .P \ .E \ .C \ .T \ .R \ .E \.) \ B"
Підсумкова програма:
   1: ЗВ'ЯЗАНИЙ (2)
   2: ВІДКРИТИ1 (4)
   4: ТОЧНО (9)
   9: ЗАКРИТИ1 (11)
  11: ЗВ'ЯЗАНИЙ (12)
  12: КІНЕЦЬ (0)
прив'язаний "СПЕКТР" на 0 (перевірка прив'язаного) stclass BOUND minlen 14
Вгадування початку збігу в sv для REx "\ b (S \ .P \ .E \ .C \ .T \ .R \ .E \.) \ B" проти "SP
.ECTRE (Спеціальний директор з питань контррозвідки, "...
Знайдено прив'язаний підстрок "СПЕКТР" зі зміщенням 0 ...
start_shift: 0 check_at: 0 s: 0 endpos: 1
Не суперечить STCLASS ...
Вгадано: збіг зі зміщенням 0
Збіг REx "\ b (S \ .P \ .E \ .C \ .T \ .R \ .E \.) \ B" проти "SPECTER (Special Exec
утиві для контррозвідки, "...
   0 | 1: ЗВ'ЯЗАНИЙ (2)
   0 | 2: ВІДКРИТИ1 (4)
   0 | 4: ТОЧНО (9)
  14 | 9: ЗАКРИТИ1 (11)
  14 | 11: ЗВ'ЯЗАНИЙ (12)
                                  не вдалося ...
Збіг не вдався
Звільнення REx: "\ b (S \ .P \ .E \ .C \ .T \ .R \ .E \.) \ B"

1
Я думаю, що слово, як правило, буде \ w словом, але цікавим моментом.
Річард Сімоєс,

1

використовувати межі слів \ b,

У моєму середовищі працює наступне (з використанням чотирьох екранів): Mac, safari Версія 10.0.3 (12602.4.8)

var myReg = new RegExp(‘\\\\b’+ variable + ‘\\\\b’, ‘g’)

1

Для тих, хто хоче перевірити Enum у своєму коді, ви можете слідувати керівництву

У Regex World ви можете використовувати ^для запуску рядка та $закінчення його. Використання їх у поєднанні з |може бути тим, що ви хочете:

^(Male)$|^(Female)$

Це поверне істину лише для Maleабо Femaleвипадку.


^і $збігатися з початком (відповідно кінцем) рядка, тому ваш приклад збігатиметься, лише якщо це єдині слова в рядку.
генеровано

і це саме те, що я хочу, коли хочу перевірити перелік! в чому проблема?
MohamadrezaRahimianGolkhandani

0

Якщо ви робите це в 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.)(.+)

і команда replace стає:

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

Пробіли - це збереження правильного форматування в моєму коді. :)


-1

Отримати всі "слова" в рядку

/([^\s]+)/g

В основному ^/sозначає перерву на пробіли (або збіг груп непробілів).
Не забувайте про gGreedy

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.