นิพจน์ปกติเพื่อแยกข้อความระหว่างวงเล็บเหลี่ยม


411

คำถาม regex ง่าย ๆ ฉันมีสตริงในรูปแบบต่อไปนี้:

this is a [sample] string with [some] special words. [another one]

การแสดงออกปกติเพื่อแยกคำภายในวงเล็บเหลี่ยมคืออะไร

sample
some
another one

หมายเหตุ: ในกรณีที่ฉันใช้งานวงเล็บไม่สามารถซ้อนกันได้

คำตอบ:


766

คุณสามารถใช้ regex ต่อไปนี้ได้ทั่วโลก :

\[(.*?)\]

คำอธิบาย:

  • \[: [เป็นเมตาชาร์และจำเป็นต้องหลบหนีหากคุณต้องการจับคู่อย่างแท้จริง
  • (.*?) : จับคู่ทุกอย่างด้วยความโลภและจับมัน
  • \]: ]เป็นเมตาชาร์และจำเป็นต้องหลบหนีหากคุณต้องการจับคู่อย่างแท้จริง

9
วิธีการอื่นของการใช้คำตอบ[^]]นั้นเร็วกว่า non-greedy ( ?) และยังทำงานร่วมกับรสชาติของ regex ที่ไม่รองรับ non-greedy อย่างไรก็ตามไม่ใช่โลภดูดีกว่า
Ipsquiggle

184
วิธีแยก[ ]ออกจากผลลัพธ์ (ผลลัพธ์)
Mickey Tin

9
@ MickeyTin ถ้าคุณใช้ Java คุณสามารถจัดกลุ่มโดยใช้กลุ่ม (1) เหนือกลุ่ม () ดังนั้น '[]' จะไม่ไปด้วยกัน
abyteneverlie

21
สิ่งนี้ตรงกับเหตุการณ์แรกเท่านั้น
hfatahi

9
คุณจะแยกวงเล็บออกจากการส่งคืนได้อย่างไร
jzadra

119
(?<=\[).+?(?=\])

จะจับเนื้อหาโดยไม่ต้องใส่เครื่องหมายวงเล็บ

  • (?<=\[) - มองในเชิงบวกสำหรับ [

  • .*? - การจับคู่ที่ไม่โลภสำหรับเนื้อหา

  • (?=\]) - มองเชิงบวกสำหรับ ]

แก้ไข: สำหรับวงเล็บซ้อนกัน regex ด้านล่างควรทำงาน:

(\[(?:\[??[^\[]*?\]))

3
@igaurav ฉันตรวจสอบแล้วและใช้งานได้ มันจะไม่ทำงานอย่างไรก็ตามในสภาพแวดล้อมที่ไม่รองรับ lookbehinds เช่น Javascript อาจเป็นกรณีของคุณ?
Adam Moszczyński

อดัม, การแก้ปัญหาวงเล็บซ้อนกันของคุณล้มเหลวเมื่อมีสตริงกับหนึ่ง.ในนั้น ...
แพทริก

89

สิ่งนี้น่าจะใช้ได้ดี:

\[([^]]+)\]

5
ในกรณีที่ฉันใช้ข้อความที่มีวงเล็บอาจรวมถึงบรรทัดใหม่และ regex นี้ทำงานในขณะที่คำตอบที่ยอมรับไม่ได้
เดฟ

1
คลาสอักขระ [^]] หมายถึงอะไร มันตรงกับอะไร?
Richard

3
@ Richard, The ^ negates คลาสอักขระ มันหมายถึง "ตัวละครที่ไม่ใช่]"
jasonbar

8
ฉันคิดว่ามันใช้งานไม่ได้ตามที่คาดไว้คุณควรใช้\[([^\[\]]*)\]เพื่อให้ได้เนื้อหาในวงเล็บส่วนใหญ่ หากคุณมองเข้าไปlfjlksd [ded[ee]22]แล้ว\[([^]]+)\]คุณจะได้รับในขณะที่การแสดงออกที่นำเสนอจะกลับมา[ded[ee] [ee]ทดสอบในลิงก์
TMC

1
คุณช่วยกรุณายกตัวอย่าง 'sed' และ 'awk' เพื่อใช้ regex นี้และแยกข้อความ ขอบคุณ
valentt

32

วงเล็บสามารถซ้อนกันได้หรือไม่

ถ้าไม่: \[([^]]+)\]จับคู่หนึ่งรายการรวมถึงวงเล็บเหลี่ยม การอ้างอิงกลับ\1จะมีรายการที่จะจับคู่ หากรสชาติของ regex ของคุณรองรับการค้นหาให้ใช้

(?<=\[)[^]]+(?=\])

สิ่งนี้จะจับคู่รายการภายในวงเล็บเท่านั้น


@KunalMukherjee: ไม่ regex สามารถจับคู่กับจำนวนครั้งใด ๆ แต่ต้องแจ้งให้ผู้ใช้ทราบถึงการใช้ regex รสชาติซ้ำ ๆ อย่างชัดเจน (ตัวอย่างเช่นโดยใช้/gแฟล็กใน JavaScript)
Tim Pietzcker

14

หากคุณไม่ต้องการรวมวงเล็บในการแข่งขันนี่คือ regex: (?<=\[).*?(?=\])

มาทำลายมันกันเถอะ

.ตรงกับตัวอักษรใด ๆ ยกเว้นจุดสิ้นสุดบรรทัด ?=เป็นlookahead บวก Lookahead เชิงบวกจะค้นหาสตริงเมื่อมีสตริงที่แน่นอนตามมา ?<=เป็นlookbehind บวก Lookbehind เชิงบวกจะค้นหาสตริงเมื่อมีสตริงที่นำหน้า ที่จะพูดนี้ ,

มองไปข้างหน้าในเชิงบวก (? =)

ค้นหา expression A โดยที่ expression B เป็นดังนี้:

A(?=B)

ดูด้านหลังเป็นบวก (? <=)

ค้นหา expression A โดยที่ expression B นำหน้า:

(?<=B)A

ทางเลือก

หากโปรแกรม regex ของคุณไม่รองรับ lookaheads และ lookbehinds คุณสามารถใช้ regex \[(.*?)\]เพื่อจับอวัยวะภายในของวงเล็บในกลุ่มจากนั้นคุณสามารถจัดการกลุ่มได้ตามความจำเป็น

regex นี้ทำงานอย่างไร

วงเล็บจับตัวละครในกลุ่ม การ.*?รับอักขระทั้งหมดระหว่างวงเล็บ (ยกเว้นสำหรับตัวยุติบรรทัดยกเว้นว่าคุณsเปิดใช้งานการตั้งค่าสถานะ) ในลักษณะที่ไม่โลภ


12

(?<=\[).*?(?=\])ใช้งานได้ดีตามคำอธิบายที่ให้ไว้ด้านบน นี่คือตัวอย่างของ Python:

import re 
str = "Pagination.go('formPagination_bottom',2,'Page',true,'1',null,'2013')"
re.search('(?<=\[).*?(?=\])', str).group()
"'formPagination_bottom',2,'Page',true,'1',null,'2013'"

1
คุณควรใช้การจัดรูปแบบรหัสสำหรับ regexes ทุกที่ที่ปรากฏ หาก regex อยู่ในข้อความแทนที่จะเป็นบล็อคโค้ดคุณสามารถใช้ backticks เพื่อจัดรูปแบบได้ ( ref )
Alan Moore

1
นอกจากนี้คำถามเกี่ยวกับวงเล็บเหลี่ยม ( []) ไม่ใช่วงเล็บ
Alan Moore

6

ในกรณีที่คุณอาจมีวงเล็บที่ไม่สมดุลกันคุณสามารถออกแบบการแสดงออกด้วยการสอบถามซ้ำคล้ายกัน

\[(([^\]\[]+)|(?R))*+\]

แน่นอนว่ามันเกี่ยวข้องกับภาษาหรือเอนจิ้น RegEx ที่คุณอาจใช้งานอยู่

สาธิต RegEx 1


นอกเหนือจากที่,

\[([^\]\[\r\n]*)\]

ตัวอย่าง RegEx 2

หรือ,

(?<=\[)[^\]\[\r\n]*(?=\])

สาธิต RegEx 3

เป็นตัวเลือกที่ดีในการสำรวจ


หากคุณต้องการที่จะลดความซับซ้อน / การแก้ไข / การสำรวจการแสดงออกก็ถูกอธิบายอยู่ด้านบนขวาของแผงregex101.com หากคุณต้องการคุณสามารถดูได้ลิงค์นี้ว่ามันจะตรงกับอินพุตตัวอย่างบางส่วนได้อย่างไร


วงจร RegEx

jex.imเห็นภาพการแสดงออกปกติ:

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

ทดสอบ

const regex = /\[([^\]\[\r\n]*)\]/gm;
const str = `This is a [sample] string with [some] special words. [another one]
This is a [sample string with [some special words. [another one
This is a [sample[sample]] string with [[some][some]] special words. [[another one]]`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}

แหล่ง

การแสดงออกปกติเพื่อให้ตรงกับวงเล็บที่สมดุล


4

ถ้าคุณต้องการเติมเพียงตัวอักษรตัวอักษรขนาดเล็กระหว่างวงเล็บเหลี่ยม az

(\[[a-z]*\])

ถ้าคุณต้องการตัวพิมพ์เล็กและพิมพ์ใหญ่ a-zA-Z

(\[[a-zA-Z]*\]) 

ถ้าคุณต้องการตัวพิมพ์เล็กและตัวอักษรตัวเลข a-zA-Z0-9

(\[[a-zA-Z0-9]*\]) 

ถ้าคุณต้องการทุกอย่างระหว่างวงเล็บเหลี่ยม

ถ้าคุณต้องการข้อความตัวเลขและสัญลักษณ์

(\[.*\])

3
([[][a-z \s]+[]])

ข้างต้นควรทำงานตามคำอธิบายต่อไปนี้

  • อักขระภายในวงเล็บเหลี่ยม [] กำหนดคลาสอักขระซึ่งหมายความว่ารูปแบบควรตรงกับอักขระอย่างน้อยหนึ่งตัวที่กล่าวถึงภายในวงเล็บเหลี่ยม

  • \ s ระบุช่องว่าง

  •  + หมายถึงอย่างน้อยหนึ่งในตัวละครที่กล่าวถึงก่อนหน้านี้ถึง +


ในกรณีที่ละเอียดอ่อนA-Zควรเพิ่มรูปแบบ: ([[][a-zA-Z \s]+[]]); ฉันคิดว่ามันเป็นวิธีที่ดีในขณะที่\ ในรูปแบบ regex ที่กำหนดในเครื่องหมายสตริง ("และ") และการผสมมือใหม่โดยการใช้แบ็กสแลชใน "หรือ" การใช้งาน!
MohaMad

คำตอบเดียวที่เหมาะกับฉันสำหรับ C ++ regex (ยกเว้น im ที่ทำด้วยการเสนอราคาแทนวงเล็บ) std::regex pattern{R"(["][a-zA-Z \s]+["])"};
StackAttack

3

รหัสนี้จะแยกเนื้อหาระหว่างวงเล็บเหลี่ยมและวงเล็บ

(?:(?<=\().+?(?=\))|(?<=\[).+?(?=\]))

(?: non capturing group
(?<=\().+?(?=\)) positive lookbehind and lookahead to extract the text between parentheses
| or
(?<=\[).+?(?=\]) positive lookbehind and lookahead to extract the text between square brackets



0

ในการจับคู่สตริงย่อยระหว่างรายการแรก [และรายการสุดท้าย ]คุณสามารถใช้

\[.*\]            # Including open/close brackets
\[(.*)\]          # Excluding open/close brackets (using a capturing group)
(?<=\[).*(?=\])   # Excluding open/close brackets (using lookarounds)

ดูการสาธิต regexและการสาธิต regex # 2 2

ใช้นิพจน์ต่อไปนี้เพื่อจับคู่สตริงระหว่างวงเล็บเหลี่ยมที่ใกล้เคียงที่สุด :

  • รวมถึงวงเล็บ:

    • \[[^][]*]- PCRE, Python re/regex , .NET, Golang, POSIX (grep, sed, bash)
    • \[[^\][]*]- ECMAScript (JavaScript, C ++ std::regex, VBA RegExp)
    • \[[^\]\[]*] - Java regex
    • \[[^\]\[]*\] - Onigmo (Ruby ต้องการการหลบหนีจากวงเล็บทุกที่)
  • ไม่รวมวงเล็บ:

    • (?<=\[)[^][]*(?=])- PCRE, Python re/ regex, .NET (C #, ฯลฯ ), ICU (R stringr), ซอฟต์แวร์ JGSoft
    • \[([^][]*)]- Bash , Golang - จับเนื้อหาระหว่างวงเล็บเหลี่ยมกับวงเล็บที่ไม่ใช้ค่า Escape ดูเพิ่มเติมที่ด้านล่าง
    • \[([^\][]*)]- JavaScript , C ++std::regex , VBARegExp
    • (?<=\[)[^\]\[]*(?=]) - Java regex
    • (?<=\[)[^\]\[]*(?=\]) - Onigmo (Ruby ต้องการการหลบหนีจากวงเล็บทุกที่)

หมายเหตุ : *ตรงกับ 0 ตัวอักษรขึ้นไปใช้+ไปเพื่อจับคู่ 1 ตัวหรือมากกว่าเพื่อหลีกเลี่ยงการจับคู่สตริงว่างในรายการ / แถวลำดับที่เป็นผลลัพธ์

เมื่อใดก็ตามที่มีการสนับสนุนการค้นหาทั้งสองวิธีโซลูชันด้านบนจะใช้เพื่อไม่รวมวงเล็บเปิด / ปิดนำหน้า / ต่อท้าย มิฉะนั้นให้ใช้การจับภาพกลุ่ม (ลิงก์ไปยังโซลูชันที่พบบ่อยที่สุดในบางภาษา)

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

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