Bagaimana cara membuat ekspresi Reguler menjadi tidak serakah?

227

Saya menggunakan jQuery. Saya memiliki string dengan blok karakter khusus (awal dan akhir). Saya ingin mendapatkan teks dari blok karakter khusus itu. Saya menggunakan objek ekspresi reguler untuk menemukan in-string. Tetapi bagaimana saya bisa memberi tahu jQuery untuk menemukan beberapa hasil ketika memiliki dua karakter khusus atau lebih?

HTML saya:

<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>

dan kode JavaScript saya:

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

  alert(filterdata); 

  //end write js 
});

Hasil saya adalah: [| cơ thử | nghiệm |] thị trường [| test2 | à test lần 2 |] ch khng khoán [| Mỹ | hari la nuoc my |] . Tapi ini bukan hasil yang saya inginkan :(. Bagaimana mendapatkan [teks] untuk kali 1 dan [demo] untuk kali 2?


Saya baru saja menyelesaikan pekerjaan saya setelah mencari info di internet ^^. Saya membuat kode seperti ini:

var filterdata = takedata.match(/(\[.*?\])/g);
  • hasil saya adalah: [| cơ thử | nghiệm |], [| test2 | đây là test lần 2 |] ini benar !. tapi saya tidak begitu mengerti hal ini. Bisakah kamu menjawab alasanku?
Rueta
sumber

Jawaban:

492

Pengubah regex non-serakah seperti bagian-bagian serakah mereka tetapi dengan ?segera mengikuti mereka:

*  - zero or more
*? - zero or more (non-greedy)
+  - one or more
+? - one or more (non-greedy)
?  - zero or one
?? - zero or one (non-greedy)
Asaf
sumber
29
mungkin berguna untuk dicatat bahwa ?dengan caranya sendiri 'satu atau nol' (tetapi serakah!). Misalnya 'bb'.replace(/b?/, 'a') //'ab'dan'bb'.replace(/c?/, 'a') //'abb'
Hashbrown
1
bagaimana c tidak ada yang cocok di sana
Muhammad Umer
1
@MuhammadUmer Saya pikir dia menyarankan itu karena ctidak akan cocok, tetapi Anda memiliki ?, yaitu 0 or 1, maka itu akan cocok 0 number of c characters, maka menggantinya. Saya tidak tahu bagaimana cara kerjanya, karena itu tidak dapat dikompilasi dalam mesin regex yang saya coba 😢
Noctis
35

Anda benar bahwa keserakahan adalah masalah:

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

Jika Anda ingin mencocokkan keduanya A--Z, Anda harus menggunakan A.*?Z( ?membuat *"enggan", atau malas).

Kadang-kadang ada cara yang lebih baik untuk melakukan ini, misalnya

A[^Z]*+Z

Ini menggunakan kelas karakter yang dinegasikan dan kuantifier posesif, untuk mengurangi backtracking, dan cenderung lebih efisien.

Dalam kasus Anda, regex akan menjadi:

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

Sayangnya regex Javascript tidak mendukung quantifier posesif, jadi Anda hanya perlu melakukan:

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

Lihat juga


Ringkasan cepat

*   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

Perhatikan bahwa quantif enggan dan posesif juga berlaku untuk {n,m}konstruksi pengulangan yang terbatas .

Contoh di Jawa:

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"
polygenelubricants
sumber
saya menyalin regex Anda ke dalam pekerjaan saya dan hasilnya adalah: quantifier tidak valid + \]) [Hentikan kesalahan ini] var filterdata = takedata.match (/ (\ [[^]]] ++ \]) /); \ n ( firebugs + Firefox) ada yang salah?
Rueta
@Rueta: rasa Javascript tampaknya tidak mendukung posesif. Saya telah mengedit jawaban saya untuk mencerminkan fakta ini. Anda bisa menggunakan satu +bukan dua.
polygenelubricants
1
Meskipun grup atom dapat digunakan sebagai pengganti quantifiers positif, JavaScript juga tidak mendukung grup atom. Tetapi ada alternatif ketiga, lihat ini: instanceof.me/post/52245507631/... -you can emulate atomic grouping with LookAhead. (?>a) becomes (?=(a))\1
Roland Pihlakas
2
Ini adalah jawaban Java untuk pertanyaan JavaScript dan Java! = JavaScript. Pembaca, perhatikan.
Roshambo
3

Saya yakin akan seperti ini

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

yang gpada akhirnya berarti global, sehingga tidak berhenti pada pertandingan pertama.

iangraham
sumber
ya, Anda benar di / g. Saya baru saja melakukan pekerjaan saya dengan jawaban Anda / g ^^. Tapi ketika saya membuat reguler /(#[.+\[)/g hasil saya adalah: [| cơ thử | nghiệm |] thị trường [| test2 | đây là test lần 2 |] ch khng khoán [| Mỹ | day la nuoc my |] :(
Rueta