Ekspresi reguler untuk berhenti pada pertandingan pertama


531

Pola regex saya terlihat seperti

<xxxx location="file path/level1/level2" xxxx some="xxx">

Saya hanya tertarik pada bagian dalam kutipan yang diberikan ke lokasi. Bukankah semudah di bawah ini tanpa saklar serakah?

/.*location="(.*)".*/

Sepertinya tidak berfungsi.


Apa sumber Anda, apakah itu HTML atau xml atau semacamnya?
Oskar Kjellin

20
Mengapa ini wiki komunitas? Ini pertanyaan nyata. Sekarang sudah terlambat.
Ahmad Mageed

1
Bahasa apa yang Anda tulis? Tolong jangan gunakan regex untuk XML. Ada begitu banyak cara yang lebih baik untuk mem-parsing XML
Oskar Kjellin

3
Tidak jika yang Anda inginkan adalah memindai atribut sederhana. Regex sesuai dan lebih cepat.
codenheim

Saya akan mengatakan bahwa jika Anda misalnya kode c # itu jauh lebih baik menggunakan LINQ untuk ini. Saya ragu bahwa akan lebih baik untuk regex jika Anda memiliki parser yang bagus
Oskar Kjellin

Jawaban:


1096

Anda perlu membuat ekspresi reguler Anda menjadi tidak rakus, karena secara default, "(.*)"akan cocok dengan semuanya "file path/level1/level2" xxx some="xxx".

Sebagai gantinya, Anda dapat membuat dot-star Anda tidak serakah, yang akan membuatnya sesedikit mungkin dengan karakter:

/location="(.*?)"/

Menambahkan ?pada quantifier ( ?, *atau +) membuatnya tidak serakah.


32
FWIW, membungkus menggunakan VIM, kebutuhan regex ini Anda menjadi sedikit berbeda: bukannya .*?itu .\{-}untuk pertandingan non-serakah.
SooDesuNe

44
Terima kasih Daniel. "Menambahkan? Pada quantifier (?, * Atau +) membuatnya tidak serakah." Tip bermanfaat untuk saya.
PhatHV

10
Itu? menggambarkan kebingungan saya dalam mencoba mencari tahu ini. Seberapa tepat.
Robbie Smith

1
Saya percaya Anda bisa mengatakan 'malas' daripada 'tidak serakah'
Manticore

50

location="(.*)"akan cocok dari "setelah location=sampai" setelah some="xxxkecuali Anda membuatnya tidak serakah. Jadi Anda baik kebutuhan .*?(yaitu membuatnya non-serakah) atau lebih baik ganti .*dengan [^"]*.


3
[^ "] * juga mungkin lebih cepat dengan sebagian besar mesin regex karena tidak perlu mencari pola setelah pola saat ini.
Jean Vincent

1
@ Tip: Anda mungkin benar, tetapi .*?notasinya lebih umum daripada[^"]*
Bondax

bagaimana kalau saya ingin memasukkan karakter pembatas menggunakan [^ "] *
Frohlich

tidak sama sekali, jika Anda tidak tahu apa artinya ^ dan [] di sini. Kebanyakan orang akan mengerti. *
Vincent Gerris


22

Gunakan pencocokan non-serakah, jika mesin Anda mendukungnya. Tambahkan ? di dalam tangkapan.

/location="(.*?)"/

11

Penggunaan quantifier Malas ?tanpa bendera global adalah jawabannya.

Misalnya,

masukkan deskripsi gambar di sini

Jika Anda memiliki bendera global /g, itu akan cocok dengan semua pertandingan dengan panjang terendah seperti di bawah ini. masukkan deskripsi gambar di sini


1

Karena Anda menggunakan subpattern yang dikuantifikasi dan sebagaimana dijelaskan dalam Perl Doc ,

Secara default, subpattern yang dikuantifikasi adalah " serakah ", yaitu, ia akan cocok sebanyak mungkin (diberikan lokasi awal tertentu) sambil tetap membiarkan sisa pola untuk mencocokkan. Jika Anda ingin agar sesuai dengan jumlah minimum yang dimungkinkan, ikuti penghitung dengan "?" . Perhatikan bahwa artinya tidak berubah, hanya "keserakahan":

*?        //Match 0 or more times, not greedily (minimum matches)
+?        //Match 1 or more times, not greedily

Jadi, untuk memungkinkan pola terkuantifikasi Anda membuat kecocokan minimum, ikuti dengan ?:

/location="(.*?)"/

1

Ini cara lain.

Inilah yang Anda inginkan. Ini malas[\s\S]*?

Item pertama: [\s\S]*?(?:location="[^"]*")[\s\S]* Ganti dengan:$1

Penjelasan : https://regex101.com/r/ZcqcUm/2


Untuk kelengkapan, ini yang terakhir. Ini serakah[\s\S]*

Item terakhir:[\s\S]*(?:location="([^"]*)")[\s\S]* Ganti dengan:$1

Penjelasan : https://regex101.com/r/LXSPDp/3


Hanya ada 1 perbedaan antara dua ekspresi reguler ini dan itu adalah ?

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.