Regex เพื่อรับสตริงระหว่างวงเล็บปีกกา


116

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

ฉันต้องการที่จะผ่านในสตริงในรูปแบบนี้และถูกส่งกลับสตริง{getThis} getThisมีใครช่วยช่วยยึดปณิธานปีใหม่ของฉันได้ไหม


คำถามที่เกี่ยวข้องใน Stack Overflow:


5
คำถามนี้ถูกเพิ่มเข้าไปในคำถามที่พบบ่อยเกี่ยวกับนิพจน์ทั่วไปของStack Overflowภายใต้ "Advanced Regex-Fu"
aliteralmind

@ Kobi: คำถามที่พบบ่อยคือ wiki ทุกคนสามารถแก้ไขได้ ดังนั้นแก้ไขมัน
aliteralmind

คำตอบ:


44

หากสตริงของคุณเป็นรูปแบบนั้นเสมอ regex จะเกินความจำเป็น:

>>> var g='{getThis}';
>>> g.substring(1,g.length-1)
"getThis"

substring(1หมายถึงการเริ่มต้นอักขระหนึ่งตัวใน (เพียงแค่ผ่านตัวอักษรแรก{) และ,g.length-1)หมายถึงนำอักขระไปจนถึง (แต่ไม่รวม) อักขระที่ความยาวสตริงลบหนึ่ง สิ่งนี้ใช้ได้ผลเนื่องจากตำแหน่งเป็นศูนย์g.length-1คือตำแหน่งสุดท้าย

สำหรับผู้อ่านอื่น ๆ กว่าโปสเตอร์เดิม: ถ้ามีจะเป็น regex ให้ใช้/{([^}]*)}/ถ้าคุณต้องการที่จะอนุญาตให้สายว่างเปล่าหรือ/{([^}]+)}/ถ้าคุณต้องการเพื่อให้ตรงกับเฉพาะเมื่อมีอย่างน้อยหนึ่งตัวอักษรระหว่างวงเล็บปีกกา ทำให้พังถล่ม:

  • /: เริ่มรูปแบบ regex
    • {: วงเล็บปีกกาตามตัวอักษร
      • (: เริ่มจับภาพ
        • [: เริ่มกำหนดคลาสของอักขระที่จะจับ
          • ^}: "อะไรก็ได้ที่ไม่ใช่}"
        • ]: ตกลงนั่นคือคำจำกัดความของชั้นเรียนทั้งหมด
        • *: จำนวนอักขระใด ๆ ที่ตรงกับคลาสที่เราเพิ่งกำหนด
      • ): จับภาพเสร็จแล้ว
    • }: วงเล็บปีกกาตามตัวอักษรต้องทำตามสิ่งที่เราจับได้ทันที
  • /: สิ้นสุดรูปแบบนิพจน์ทั่วไป

7
สตริงย่อยเป็นหนึ่งในสิ่งที่เปลี่ยนแปลงไปตามภาษาที่คุณใช้งาน Javascript จะหยุดดัชนีที่ PHP ใช้ความยาวของผลลัพธ์สุดท้ายที่ต้องการ (เว้นแต่จะเป็นค่าลบซึ่งในกรณีนี้จะต้องใช้จำนวนอักขระในการลบ) , C # แตกต่างอีกแล้ว ... ดีจังงง.
jvenema

2
... และ Python ก็มีการแบ่งส่วนซึ่ง IMO ดีกว่าสิ่งอื่นใด: p.
พอล

27
หวาน แต่ไม่แน่ใจว่าเป็นสำนวนปกติอย่างไร บางทีเขาอาจจะถามหา regex และฉันก็มาที่นี่เพื่อรับคำตอบเดียวกัน .. น่าเศร้าที่คำตอบไม่เกี่ยวข้องกับคำถาม ..
baash05

5
@ baash05 ถ้าคุณอ่านคำถามทั้งหมด OP ไม่ต้องการเรียนรู้ regex ด้วยซ้ำดังนั้นฉันไม่คิดว่ามันเป็นแบบฝึกหัดทางวิชาการที่คุณดูเหมือนจะแนะนำ
Kev

2
ฉันต้องการทำ -1 เพราะคำถามกำลังถามหาregexฉันกำลังค้นหาregexแต่คำตอบที่ได้รับการยอมรับนั้นไร้ประโยชน์สำหรับฉันโดยสิ้นเชิง (ในขณะที่คำถามดูเหมือนมีแนวโน้มมาก) หลังจากอ่านความคิดเห็นแรกแล้วฉันต้องยอมรับว่าถ้าฉันจะตอบคำถามนี้ก่อนฉันก็สามารถตอบในลักษณะเดียวกัน / คล้ายกันได้ ... ในท้ายที่สุด +1
Shadyyx

250

ลอง

/{(.*?)}/

นั่นหมายความว่าจับคู่อักขระใด ๆ ระหว่าง {และ} แต่อย่าโลภ - จับคู่สตริงที่สั้นที่สุดซึ่งลงท้ายด้วย} (the? stops * being greedy) วงเล็บช่วยให้คุณแยกส่วนที่ตรงกัน

อีกวิธีหนึ่งก็คือ

/{([^}]*)}/

สิ่งนี้จับคู่อักขระใด ๆ ยกเว้น a} char (วิธีอื่นในการไม่โลภ)


นี่เป็นสิ่งที่ยอดเยี่ยม แต่เป็นไปได้ไหมที่จะจับคู่อะไรระหว่างชุดค่าผสมของวงเล็บปีกกา เช่น: "{this should be matched} this shouldnt {this kinda should again} และอื่น ๆ {on}"? ฉันต้องการดึงค่าซึ่งไม่อยู่ในวงเล็บปีกกา นอกจากนี้: จะไม่ใช้วงเล็บปีกกาในประโยคและไม่มีการซ้อนกัน (สิ่งนี้จะไม่เกิดขึ้น: "{some {text}}") ใครมีความคิดจะทำ :)? ขอบคุณ! (ps: โหวตวิธีแก้ปัญหานี้)
อิกอร์

4
มันไม่ได้จับทุกอย่างระหว่างวงเล็บปีกกามันจับทุกอย่างระหว่างวงเล็บปีกกาและวงเล็บปีกกาด้วยตัวเอง คุณจะจับเฉพาะสิ่งที่อยู่ในวงเล็บปีกกาได้อย่างไร?
Reality-Torrent

1
ฉันชอบที่คุณไม่จำเป็นต้องหนีวงเล็บปีกกาที่นี่เนื่องจากตัวแยกวิเคราะห์ regex ดูเหมือนจะตระหนักว่าพวกเขาไม่ใช่ตัวระบุปริมาณ ... ฉันกำลังทำสิ่งนี้ใน python แต่ฉันคิดว่า regexes จาวาสคริปต์ทำงานเช่นนั้น ด้วย
drevicko

3
การเพิ่มgต่อท้ายทำให้เป็นการค้นหาทั่วโลก ดูตัวอย่างการทำงาน
เบนจามิน

1
@ Reality-Torrent ฉันก็เห็นเช่นกันว่ามันจับวงเล็บปีกกาถ้าฉันระบุตัวเลือก g เพื่อรับการแข่งขันทั้งหมด ปรากฎว่าฉันควรใช้ Regex.exec ในการวนซ้ำแทน string.match ใน Javascript เพื่อให้มีทั้งแฟล็ก g และอนุญาตให้จับกลุ่ม ดูdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
แฟรงค์

150
/\{([^}]+)\}/

/        - delimiter
\{       - opening literal brace escaped because it is a special character used for quantifiers eg {2,3}
(        - start capturing
[^}]     - character class consisting of
    ^    - not
    }    - a closing brace (no escaping necessary because special characters in a character class are different)
+        - one or more of the character class
)        - end capturing
\}       - the closing literal brace
/        - delimiter

@meouw sa = s.split ("/ \ {([^}] +) \} /"); ทำให้เกิดข้อผิดพลาดในการคอมไพล์ การทำซ้ำที่ผิดกฎหมายอักขระหลบหนีไม่ถูกต้อง
likejudo

@Anil คุณดูเหมือนจะใช้สตริงเป็นอาร์กิวเมนต์แยกของคุณแทนที่จะเป็นนิพจน์ทั่วไป คุณพยายามจะทำอะไร?
meouw

30

ลองสิ่งนี้:

/[^{\}]+(?=})/g

ตัวอย่างเช่น

Welcome to RegExr v2.1 by #{gskinner.com},  #{ssd.sd} hosted by Media Temple!

จะกลับมาgskinner.com, ssd.sd.


1
เยี่ยมมากคุณช่วยอธิบายได้ไหมว่าทำไมคุณถึงใช้\}ในบล็อกแรก
Uzair Ali

1
ดี แต่จะตรงกับกลุ่มใด ๆ ที่ลงท้ายด้วย}แม้ว่าจะไม่ได้เริ่มต้นด้วย{ก็ตาม
Ahmad Ibrahim

1
นี่เป็นคำตอบเดียวที่ใช้งานได้จริง
pldg

คำอธิบาย: แม้ว่า [^ \ {\}] + จะจับคู่อะไรก็ได้ที่ไม่ใช่วงเล็บปีกกา แต่การยืนยันของผู้มองหา (? =}) จะทำให้แน่ใจว่าจะส่งผ่านเฉพาะส่วนที่อยู่หน้าวงเล็บปีกกาเท่านั้น ด้วย / ... / g เราได้รับเหตุการณ์ทั้งหมดไม่ใช่เฉพาะครั้งแรก
0 -_- 0

20

นี่เป็นวิธีง่ายๆโดยใช้การแทนที่จาวาสคริปต์

var st = '{getThis}';

st = st.replace(/\{|\}/gi,''); // "getThis"

เนื่องจากคำตอบที่ยอมรับข้างต้นชี้ให้เห็นว่าปัญหาเดิมสามารถแก้ไขได้อย่างง่ายดายด้วยสตริงย่อย แต่การใช้การแทนที่สามารถแก้ปัญหาการใช้งานที่ซับซ้อนกว่าได้

หากคุณมีสตริงเช่น "randomstring999 [fieldname]" คุณใช้รูปแบบที่แตกต่างกันเล็กน้อยเพื่อรับชื่อฟิลด์

var nameAttr = "randomstring999[fieldname]";

var justName = nameAttr.replace(/.*\[|\]/gi,''); // "fieldname"

15

ตัวนี้ทำงานใน Textmate และจับคู่ทุกอย่างในไฟล์ CSS ระหว่างวงเล็บปีกกา

\{(\s*?.*?)*?\}

selector {. . matches here including white space. . .}

หากคุณต้องการคืนเนื้อหาเพิ่มเติมให้รวมไว้ในวงเล็บอีกชุดหนึ่งดังนี้:

\{((\s*?.*?)*?)\}

และคุณสามารถเข้าถึงเนื้อหาผ่าน $ 1

สิ่งนี้ใช้ได้กับฟังก์ชันเช่นกัน แต่ฉันยังไม่ได้ทดสอบกับวงเล็บปีกกาซ้อนกัน


14

คุณต้องการใช้ regex lookahead และ lookbehind สิ่งนี้จะให้เฉพาะสิ่งที่อยู่ในวงเล็บปีกกา:

(?<=\{)(.*?)(?=\})

ควรมีแบ็กสแลชหนีเครื่องหมายปีกกาด้านบน พวกเขาถูกปลดออกจากการส่งของฉัน
Robert Cesaric

1
ขอบคุณสิ่งนี้ช่วยฉันในวันนี้
ProfessionalAmateur

ข้อเสียของวิธีนี้หรือไม่?
Somatik

5
@ Somatik ใช่การมองเชิงลบและเบื้องหลังไม่ได้รับการสนับสนุนใน ECMAScript
RobG

หมายเหตุ: ตัวอย่างนี้ใช้ได้กับ Java ส่งคืนค่าทั้งหมดในวงเล็บปีกกาทั้งหมด
Multiplexor

14

ลองทำตามนี้

let path = "/{id}/{name}/{age}";
const paramsPattern = /[^{\}]+(?=})/g;
let extractParams = path.match(paramsPattern);
console.log("extractParams", extractParams) // prints all the names between {} = ["id", "name", "age"]

1
สิ่งที่ฉันต้องการ :) สิ่งนี้จะส่งคืนผลลัพธ์โดยไม่ต้องจัดฟันวิธีอื่น ๆ จะกลับมาพร้อมกับมัน
Al-Mothafar

ยอดเยี่ยมคำตอบที่ดีที่สุดที่นี่
michal.jakubeczy

4

Regex สำหรับการรับอาร์เรย์ของสตริงที่มีวงเล็บปีกกาล้อมรอบเกิดขึ้นในสตริงแทนที่จะค้นหาเหตุการณ์แรก

 /\{([^}]+)\}/gm 

4

ฉันได้ตรวจสอบคำตอบอื่น ๆ แล้วและดูเหมือนว่าตรรกะที่สำคัญจะขาดหายไปจากพวกเขา กล่าวคือเลือกทุกอย่างระหว่างสองวงเล็บที่ใช้งานง่าย แต่ไม่ใช่วงเล็บ

ดังนั้นนี่คือคำตอบของฉัน

\{([^{}]+)\}

3
var re = /{(.*)}/;
var m = "{helloworld}".match(re);
if (m != null)
    console.log(m[0].replace(re, '$1'));

.replace(/.*{(.*)}.*/, '$1')ขออภัยที่ง่ายกว่าจะส่งคืนสตริงทั้งหมดหาก regex ไม่ตรงกัน ข้อมูลโค้ดด้านบนสามารถตรวจจับคู่ได้ง่ายขึ้น



2

คุณสามารถใช้การเรียกซ้ำของ regex นี้เพื่อจับคู่ everythin ระหว่างอื่น ๆ ได้{}(เช่นข้อความ JSON):

\{([^()]|())*\}

ดี แต่สิ่งนี้รวบรวมเฉพาะเนื้อหาภายในวงเล็บปีกกาแบบซ้อนเท่านั้น
Dominic

ไม่จับภาพหากเนื้อหามี ()
Mert Mertce

1

แม้สิ่งนี้จะช่วยฉันในขณะที่พยายามแก้ปัญหาของใครบางคน

แยกเนื้อหาภายในวงเล็บปีกกา ( {}) มีรูปแบบเช่น, {'day': 1, 'count': 100}.

ตัวอย่างเช่น:

#include <iostream> 
#include <regex> 
#include<string> 
using namespace std; 

int main() 
{ 
    //string to be searched
    string s = "{'day': 1, 'count': 100}, {'day': 2, 'count': 100}";

    // regex expression for pattern to be searched 
    regex e ("\\{[a-z':, 0-9]+\\}");
    regex_token_iterator<string::iterator> rend;

    regex_token_iterator<string::iterator> a ( s.begin(), s.end(), e );
    while (a!=rend) cout << " [" << *a++ << "]";
    cout << endl;

    return 0; 
}

เอาท์พุท:

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