Regex จับคู่คำทั้งหมดเท่านั้น


92

ฉันมีนิพจน์นิพจน์ทั่วไปที่ฉันใช้เพื่อค้นหาคำทั้งหมดในบล็อกเนื้อหาที่กำหนดไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่ที่อยู่ในอภิธานศัพท์ที่เก็บไว้ในฐานข้อมูล นี่คือรูปแบบของฉัน:

/($word)/i

ปัญหาคือถ้าฉันใช้ /(Foo)/iแล้วคำเหมือนFoodได้รับการจับคู่ จำเป็นต้องมีช่องว่างหรือขอบเขตคำทั้งสองด้านของคำ

ฉันจะแก้ไขนิพจน์ของฉันให้จับคู่เฉพาะคำได้อย่างไรFooเมื่อเป็นคำที่ขึ้นต้นกลางหรือท้ายประโยค

คำตอบ:


126

ใช้ขอบเขตคำ:

/\b($word)\b/i

หรือหากคุณกำลังค้นหา "SPECTER" เช่นในตัวอย่างของ Sinan Ünür:

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

1
ฉันเพิ่งพิมพ์คำตอบฉบับยาวเมื่อคุณโพสต์ :)
ZombieSheep

@RichardSimoes \b(<|>=)\bไม่ตรงกัน>=
alhelal

@RichardSimoes และ\b[-|+][0-9]+\bตรงกับ+10ใน43E+10. ทั้งที่ฉันไม่ต้องการ
alhelal

จะเกิดอะไรขึ้นถ้าฉันต้องการค้นหาคำที่ไม่ได้ต่อท้ายหรือไม่มีอยู่ในคำอื่นใด ตรรกะนี้จะใช้ไม่ได้
Prasanna Sasne

ใครจะได้รับตัวดำเนินการเปรียบเทียบทางคณิตศาสตร์> = และ <=?
AntonSack

52

เพื่อให้ตรงกับคำใด ๆ คุณจะใช้รูปแบบ (\w+)

สมมติว่าคุณใช้ PCRE หรือสิ่งที่คล้ายกัน:

ป้อนคำอธิบายภาพที่นี่

ภาพหน้าจอด้านบนที่นำมาจากตัวอย่างจริงนี้: http://regex101.com/r/cU5lC2

จับคู่คำทั้งหมดในบรรทัดคำสั่งกับ (\w+)

ฉันจะใช้phpsh interactive shellบนUbuntu 12.10เพื่อสาธิตเอ็นจิ้PCRE regexผ่านวิธีการที่เรียกว่า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 มีสตริงโผหรือผายลม 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มีขอบเขตของคำไม่อยู่ในเนื้อหา:\bfarty


น. น. ไม่ใช่คำพูด?
minion

หากคุณต้องการบังคับให้ am และ pm เป็นคำ (ไม่ใช่เป็นคำย่อ) ให้เพิ่มจุดเป็นอักขระคำสำหรับเครื่องมือ regex ของคุณ สำหรับคุณดูเหมือนว่าคุณได้กำหนดช่วงเวลาไม่ใช่อักขระคำดังนั้นคำ regex จะไม่เป็นแบบตัวต่อตัวและเป็นคำจำกัดความมาตรฐานของ "คำ" ที่คุณได้รับการสอนในพจนานุกรมยุโรปสำหรับลูกผสมยุโรป ภาษา (หรือภาษาอื่น ๆ สำหรับเรื่องนั้น)
Eric Leschinski

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)
"SPECTER" ทอดสมอที่ 0 (กำลังตรวจสอบจุดยึด) stclass BOUND minlen 14
การคาดเดาจุดเริ่มต้นของการแข่งขันใน sv สำหรับ REx "\ b (S \ .P \ .E \ .C \ .T \ .R \ .E \.) \ b" เทียบกับ "SP
.ECTRE (Special Executive for Counter-intelligence, "...
พบสถานีย่อยแบบยึด "SPECTER" ที่ออฟเซ็ต 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 แต่เป็นประเด็นที่น่าสนใจ
Richard Simões

1

ใช้ขอบเขตของคำ \ b,

สิ่งต่อไปนี้ (โดยใช้ค่า Escape สี่ตัว) ทำงานในสภาพแวดล้อมของฉัน: Mac, Safari เวอร์ชัน 10.0.3 (12602.4.8)

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

1

สำหรับผู้ที่ต้องการตรวจสอบ Enum ในรหัสของพวกเขาคุณสามารถทำตามคำแนะนำ

ใน Regex World คุณสามารถใช้^สำหรับการเริ่มต้นสตริงและ$สิ้นสุดได้ การใช้ร่วมกับ|สิ่งที่คุณต้องการ:

^(Male)$|^(Female)$

มันจะส่งคืนจริงเฉพาะสำหรับMaleหรือFemaleกรณี


^และ$จับคู่จุดเริ่มต้น (ตามลำดับจุดสิ้นสุด) ของบรรทัดดังนั้นตัวอย่างของคุณจะจับคู่ก็ต่อเมื่อคำเหล่านั้นเป็นคำเดียวในบรรทัดเท่านั้น
63

และนี่คือสิ่งที่ฉันต้องการเมื่อฉันต้องการตรวจสอบ enum! อะไรคือปัญหา?
MohamadrezaRahimianGolkhandani

0

หากคุณกำลังทำใน Notepad ++

[\w]+ 

จะให้ทั้งคำและคุณสามารถเพิ่มวงเล็บเพื่อให้เป็นกลุ่มได้ ตัวอย่าง: conv1 = Conv2D(64, (3, 3), activation=LeakyReLU(alpha=a), padding='valid', kernel_initializer='he_normal')(inputs). ฉันต้องการย้ายLeakyReLUเข้าไปในบรรทัดของตัวเองเป็นความคิดเห็นและแทนที่การเปิดใช้งานปัจจุบัน ใน notepad ++ สามารถทำได้โดยใช้คำสั่ง follow find:

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

และคำสั่งแทนที่กลายเป็น:

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

ช่องว่างคือการจัดรูปแบบที่ถูกต้องในรหัสของฉัน :)


-1

รับ "คำ" ทั้งหมดในสตริง

/([^\s]+)/g

โดยทั่วไป^/sหมายถึงการแบ่งช่องว่าง (หรือจับคู่กลุ่มที่ไม่ใช่ช่องว่าง)
อย่าลืมgสำหรับโลภ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.