Regex: ระบุ "ช่องว่างหรือจุดเริ่มต้นของสตริง" และ "ช่องว่างหรือจุดสิ้นสุดของสตริง"


127

สมมติว่าคุณพยายามจับคู่รูปแบบ "stackoverflow"

คุณต้องการสิ่งต่อไปนี้:

 this is stackoverflow and it rocks [MATCH]

 stackoverflow is the best [MATCH]

 i love stackoverflow [MATCH]

 typostackoverflow rules [NO MATCH]

 i love stackoverflowtypo [NO MATCH]

ฉันรู้วิธีแยกวิเคราะห์ stackoverflow หากมีช่องว่างบนทั้งสองไซต์โดยใช้:

/\s(stackoverflow)\s/

เช่นเดียวกับถ้าอยู่ที่จุดเริ่มต้นหรือจุดสิ้นสุดของสตริง:

/^(stackoverflow)\s/

/\s(stackoverflow)$/

แต่คุณจะระบุ "ช่องว่างหรือจุดสิ้นสุดของสตริง" และ "ช่องว่างหรือจุดเริ่มต้นของสตริง" โดยใช้นิพจน์ทั่วไปได้อย่างไร?

คำตอบ:


172

คุณสามารถใช้สิ่งต่อไปนี้:

\b      #A word break and will work for both spaces and end of lines.
(^|\s)  #the | means or. () is a capturing group. 


/\b(stackoverflow)\b/

นอกจากนี้หากคุณไม่ต้องการรวมพื้นที่ในการแข่งขันคุณสามารถใช้ lookbehind / ข้างหน้า

(?<=\s|^)         #to look behind the match
(stackoverflow)   #the string you want. () optional
(?=\s|$)          #to look ahead.

8
\bเป็นการยืนยันความกว้างเป็นศูนย์ มันไม่เคยกินอักขระใด ๆ ไม่จำเป็นต้องห่อให้เป็นรูปลักษณ์ภายนอก
Alan Moore

2
โปรดทราบว่าในการใช้งาน regexp ส่วนใหญ่\bเป็นASCII มาตรฐานเท่านั้นกล่าวคือไม่มีการสนับสนุน Unicode หากคุณต้องการจับคู่คำ Unicode คุณไม่มีทางเลือกอื่นนอกจากใช้สิ่งนี้แทน: stackoverflow.com/a/6713327/1329367
Mahn

4
วิธีที่ง่ายกว่าในการยกเว้นการเลือกกลุ่มจากการแข่งขันคือ(?:^|\s)
user2426679

7
สำหรับ python ให้แทนที่(?<=\s|^)ด้วย(?:(?<=\s)|(?<=^)). มิฉะนั้นคุณจะได้รับerror: look-behind requires fixed-width pattern
user2426679

4
โดย\bจะพิจารณาอักขระอื่นเช่น " ." เป็นตัวแบ่งคำในขณะที่ผู้ถามพูดว่า "เว้นวรรค" โดยเฉพาะ วิธีแก้ปัญหาของ @ gordy น่าจะดีกว่า
Mikhail T.

66

(^|\s)จะจับคู่ช่องว่างหรือจุดเริ่มต้นของสตริงและ($|\s)สำหรับช่องว่างหรือจุดสิ้นสุดของสตริง มันรวมกัน:

(^|\s)stackoverflow($|\s)

4
นี่คือสิ่งเดียวที่เหมาะกับฉัน ขอบคุณ @gordy
robsonrosa

2
$1string$2ถ้าคุณใช้รูปแบบนี้จะเปลี่ยนจำเพื่อให้ช่องว่างในผลแทนที่โดยการแทนที่ด้วยรูปแบบ
Mahn

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

18

นี่คือสิ่งที่ฉันจะใช้:

 (?<!\S)stackoverflow(?!\S)

กล่าวอีกนัยหนึ่งคือจับคู่ "stackoverflow" หากไม่ได้นำหน้าด้วยอักขระที่ไม่ใช่ช่องว่างและไม่ตามด้วยอักขระที่ไม่ใช่ช่องว่าง

นี่เป็นวิธีที่ดีกว่า (IMO) มากกว่าวิธีการ "space-or-anchor" และไม่ถือว่าสตริงเริ่มต้นและลงท้ายด้วยอักขระคำเช่นเดียวกับ\bวิธีการ


1
คำอธิบายที่ดีว่าทำไมถึงใช้สิ่งนี้ ฉันจะเลือกสิ่งนี้อย่างไรก็ตามสตริงที่ทดสอบนั้นเป็นบรรทัดเดียวเสมอ
anonymous-one

7

\b จับคู่ที่ขอบเขตคำ (โดยไม่จับคู่อักขระใด ๆ จริงๆ) ดังนั้นสิ่งต่อไปนี้ควรทำในสิ่งที่คุณต้องการ:

\bstackoverflow\b

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