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.

publicRavi
sumber
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.

Daniel Vandersluis
sumber
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 [^"]*.

sepp2k
sumber
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
31

Bagaimana tentang

.*location="([^"]*)".*

Ini menghindari pencarian tanpa batas dengan. * Dan akan sama persis dengan kutipan pertama.

pengguna193690
sumber
Karena perbedaan dalam grep yang di atas harus menjadi pola yang disukai jika portabilitas menjadi perhatian.
Josh Habdas
22

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

/location="(.*?)"/
codenheim
sumber
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

Uddhav Gautam
sumber
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="(.*?)"/
Mohammad Kanan
sumber
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 ?

Stephen Sherry
sumber