วิธีที่จะทำให้การแสดงออกปกติเป็นไม่โลภ?


227

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

HTML ของฉัน:

<div id="container">
    <div id="textcontainer">
     Cuc chiến pháp lý gia [|cơ thử|nghim|] th trường [|test2|đây là test ln 2|] chng khoán [|Mỹ|day la nuoc my|] và ngân hàng đầu tư quyn lc nht Ph Wall mi ch bt đầu.
    </div>
</div>

และรหัส JavaScript ของฉัน:

$(document).ready(function() {
  var takedata = $("#textcontainer").text();
  var test = 'abcd adddb';
  var filterdata = takedata.match(/(\[.+\])/);

  alert(filterdata); 

  //end write js 
});

ผลของฉันคือ: [| cơ Thu | Nghiem |] ThịTrường [| test2 | Djay làทดสอบlần 2 |] Chung สว่าน [| ฉัน | วันลา nuoc ฉัน |] แต่นี่ไม่ใช่ผลลัพธ์ที่ฉันต้องการ :( จะได้รับ [text] ครั้งที่ 1 และ [demo] ครั้งที่ 2 ได้อย่างไร


ฉันเพิ่งทำงานเสร็จหลังจากค้นหาข้อมูลบนอินเทอร์เน็ตแล้ว ^^ ฉันทำรหัสเช่นนี้:

var filterdata = takedata.match(/(\[.*?\])/g);
  • ผลลัพธ์ของฉันคือ: [| cơthử | nghiệm |], [| test2 | đâylàทดสอบlần 2 |] นี่ถูกต้อง! แต่ฉันไม่เข้าใจสิ่งนี้จริงๆ คุณตอบฉันได้ไหม

คำตอบ:


492

ตัวดัดแปลง regex ที่ไม่ใช่โลภเป็นเหมือนตัวนับโลภของพวกเขา แต่?ทันทีที่ติดตามพวกเขา:

*  - zero or more
*? - zero or more (non-greedy)
+  - one or more
+? - one or more (non-greedy)
?  - zero or one
?? - zero or one (non-greedy)

29
อาจเป็นประโยชน์ที่จะทราบว่า?ในความหมายของตัวเอง 'หนึ่งหรือศูนย์' (แต่เป็นโลภ!) เช่น'bb'.replace(/b?/, 'a') //'ab'และ'bb'.replace(/c?/, 'a') //'abb'
Hashbrown

1
คไม่มีอะไรตรงกับที่นั่นอย่างไร
Muhammad Umer

1
@ MuhammadUmer ฉันคิดว่าเขาแนะนำว่าเพราะcไม่ตรงกัน แต่คุณมี?ซึ่งก็คือ0 or 1มันจะเข้า0 number of c charactersกันดังนั้นแทนที่มัน ฉันไม่รู้ว่ามันทำงานอย่างไรเพราะนั่นไม่ได้รวบรวมในโปรแกรม regex ใด ๆ ที่ฉันลอง tried
Noctis

35

คุณถูกต้องว่าความโลภเป็นปัญหา:

--A--Z--A--Z--
  ^^^^^^^^^^
     A.*Z

หากคุณต้องการจับคู่ทั้งคู่A--Zคุณต้องใช้A.*?Z( ?ทำให้*"ลังเล" หรือขี้เกียจ)

บางครั้งมีวิธีที่ดีกว่าในการทำเช่นแม้ว่า

A[^Z]*+Z

สิ่งนี้ใช้คลาสของอักขระที่ถูกปฏิเสธและปริมาณที่มีเจ้าของเพื่อลดการย้อนรอยและน่าจะมีประสิทธิภาพมากกว่า

ในกรณีของคุณ regex จะเป็น:

/(\[[^\]]++\])/

น่าเสียดายที่ Javascript regex ไม่สนับสนุน quantifier ที่เป็นเจ้าของดังนั้นคุณต้องทำดังนี้

/(\[[^\]]+\])/

ดูสิ่งนี้ด้วย


สรุปด่วน

*   Zero or more, greedy
*?  Zero or more, reluctant
*+  Zero or more, possessive

+   One or more, greedy
+?  One or more, reluctant
++  One or more, possessive

?   Zero or one, greedy
??  Zero or one, reluctant
?+  Zero or one, possessive

โปรดทราบว่าปริมาณที่ไม่เต็มใจและความเป็นเจ้าของสามารถนำไปใช้กับการ{n,m}สร้างซ้ำที่ จำกัดได้

ตัวอย่างใน Java:

System.out.println("aAoZbAoZc".replaceAll("A.*Z", "!"));  // prints "a!c"
System.out.println("aAoZbAoZc".replaceAll("A.*?Z", "!")); // prints "a!b!c"

System.out.println("xxxxxx".replaceAll("x{3,5}", "Y"));  // prints "Yx"
System.out.println("xxxxxx".replaceAll("x{3,5}?", "Y")); // prints "YY"

ฉันคัดลอก regex ของคุณลงในงานของฉันและผลลัพธ์คือ: quantifier ที่ไม่ถูกต้อง + \]) [หยุดข้อผิดพลาดนี้] var filterdata = takedata.match (/ (\ [[^ \]] ++ \]) /); \ n ( firebugs + Firefox) มีอะไรผิดปกติ?
Rueta

@Rueta: เห็นได้ชัดว่า Javascript รสชาติไม่สนับสนุนการเป็นเจ้าของ ฉันได้แก้ไขคำตอบของฉันเพื่อสะท้อนความจริงนี้ คุณสามารถใช้เพียงหนึ่ง+แทนสอง
polygenelubricants

1
แม้ว่ากลุ่มอะตอมสามารถนำมาใช้แทนปริมาณที่ครอบครอง, JavaScript ไม่สนับสนุนกลุ่มอะตอมเช่นกัน แต่มีทางเลือกที่สามให้ดูสิ่งนี้: instanceof.me/post/52245507631/… -you can emulate atomic grouping with LookAhead. (?>a) becomes (?=(a))\1
Roland Pihlakas

2
นี่คือคำตอบ Java สำหรับคำถาม JavaScript และ Java! = JavaScript ผู้อ่านจด
Roshambo

3

ฉันเชื่อว่ามันจะเป็นเช่นนี้

takedata.match(/(\[.+\])/g);

gในตอนท้ายหมายถึงทั่วโลกจึงไม่ได้หยุดอยู่ที่การแข่งขันครั้งแรก


ใช่คุณอยู่ใน / g ฉันเพิ่งจะทำงานกับคำตอบของคุณ / g ^^ แต่เมื่อฉันทำให้ปกติ/(\ه.+\ธรรมดา)/gผลของฉันคือ: [| cơthử | nghiệm |] thịtrường [| test2 | đâylàทดสอบlần 2 |] chứngkhoán [| Mỹ | วัน la nuoc ของฉัน |] :(
Rueta
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.