Bagaimana Anda menemukan "It's" dalam string yang hanya berisi "Is"? Saya akan memperbaikinya untuk Anda, tetapi saya tidak tahu konvensi kutipan / pelolosan tunggal mana yang berlaku dalam bahasa yang Anda gunakan.
Sebenarnya, melihat tanggalnya, saya melihat bahwa pertanyaan yang lain adalah duplikat dari pertanyaan ini. Either way, pastikan untuk memeriksa jawaban saya .
ridgerunner
@ridgerunner: Saya memberikan suara untuk menutup ini seperti yang Anda sarankan. Memang benar, pertanyaan lain lebih baru, tetapi juga jauh lebih baik (sebagian besar berkat jawaban Anda).
Alan Moore
Jawaban:
160
/"(?:[^"\\]|\\.)*"/
Bekerja di The Regex Coach dan PCRE Workbench.
Contoh pengujian di JavaScript:
var s =' function(){ return " Is big \\"problem\\", \\no? "; }';var m = s.match(/"(?:[^"\\]|\\.)*"/);if(m !=null)
alert(m);
Masuk akal. Bahasa Inggris biasa: Dua tanda kutip yang mengelilingi nol atau lebih dari "karakter apa pun yang bukan kutipan atau garis miring terbalik" atau "garis miring terbalik yang diikuti oleh karakter apa pun". Aku tidak percaya aku tidak berpikir untuk melakukan itu ...
Ajedi32
7
Saya akan menjawab sendiri. =) (?:...)adalah kelompok pasif atau non-penangkap. Itu berarti tidak dapat direferensikan nanti.
magras
setelah banyak mencari dan menguji banyak, ini adalah solusi nyata dan satu-satunya yang saya temukan untuk masalah umum ini. Terima kasih!
cancerbero
10
Terima kasih untuk ini. saya ingin mencocokkan tanda kutip tunggal juga jadi saya akhirnya menyesuaikannya dengan ini:/(["'])(?:[^\1\\]|\\.)*?\1/
c.nanorc adalah tempat pertama saya pergi. Tidak bisa membuatnya bekerja sebagai bagian dari string C literal sampai dua kali melarikan diri dari semuanya seperti ini" \"(\\\\.|[^\\\"])*\" "
hellork
Ini bekerja dengan fungsi egrep dan re_comp / re_exec dari libc.
fk0
19
Seperti yang diberikan oleh ePharaoh, jawabannya adalah
/"([^"\\]*(\\.[^"\\]*)*)"/
Agar hal di atas berlaku untuk string kutip tunggal atau kutip ganda, gunakan
Ini adalah satu-satunya set yang berfungsi untuk saya dengan string kutipan berukuran 1,5 KB besar yang berisi 99 pelolosan. Setiap ekspresi lain di halaman ini rusak di editor teks saya dengan kesalahan luapan. Meskipun sebagian besar di sini berfungsi di browser, hanya sesuatu yang perlu diingat. Biola: jsfiddle.net/aow20y0L
Beejor
3
Lihat jawaban @ MarcAndrePoulin di bawah untuk penjelasannya.
mulai
10
Sebagian besar solusi yang disediakan di sini menggunakan jalur pengulangan alternatif yaitu (A | B) *.
Anda mungkin mengalami stack overflows pada input yang besar karena beberapa compiler pola mengimplementasikannya menggunakan rekursi.
Sesuatu seperti ini:,
"(?:[^"\\]*(?:\\.)?)*"atau yang disediakan oleh Guy Bedford akan mengurangi jumlah langkah penguraian untuk menghindari sebagian besar luapan tumpukan.
Mengganti \"dan .melewati tanda kutip lolos sementara pembilang malas *?memastikan bahwa Anda tidak melewati akhir string yang dikutip. Bekerja dengan kelas .NET Framework RE
Diambil langsung dari man perlresistem Linux dengan Perl 5.22.0 diinstal. Sebagai pengoptimalan, ekspresi reguler ini menggunakan bentuk 'posesif' dari keduanya +dan *untuk mencegah mundur, karena telah diketahui sebelumnya bahwa string tanpa kutipan penutup tidak akan cocok dalam hal apa pun.
Bagus, tetapi terlalu fleksibel untuk permintaan (akan cocok dengan tanda kutip tunggal ...). Dan dapat disederhanakan menjadi /".*?(?<!\)"/ kecuali saya melewatkan sesuatu. Oh, dan beberapa bahasa (mis. JavaScript) sayangnya tidak memahami ekspresi lookbehind negatif.
PhiLho
1
@PhiLho, hanya menggunakan satu (? <! \\) akan gagal pada garis miring terbalik yang lolos di akhir string. Benar tentang melihat ke belakang dalam JavaScript.
Markus Jarderot
4
Yang ini berfungsi sempurna di PCRE dan tidak termasuk dalam StackOverflow.
"(.*?[^\\])??((\\\\)+)?+"
Penjelasan:
Setiap string yang dikutip dimulai dengan Char: " ;
Ini mungkin berisi sejumlah karakter: .*?{Lazy match}; diakhiri dengan karakter non escape[^\\] ;
Pernyataan (2) adalah Lazy (!) Opsional karena string boleh kosong (""). Begitu:(.*?[^\\])??
Akhirnya, setiap string yang dikutip diakhiri dengan Char ( "), tetapi bisa diawali dengan pasangan tanda escape nomor genap (\\\\)+; dan itu adalah Greedy (!) opsional: ((\\\\)+)?+{Greedy matching}, string bacause bisa kosong atau tanpa pasangan penutup!
ini adalah solusi yang sangat baik, tetapi [^\1]harus diganti dengan .karena tidak ada yang namanya anti-referensi-referensi, dan itu tidak masalah. kondisi pertama akan selalu cocok sebelum hal buruk bisa terjadi.
Seph Reed
@SephReed - mengganti[^\1] dengan .efektif akan mengubah regex ini untuk ("|').*?\1dan kemudian akan cocok "foo\"di "foo \" bar". Meskipun demikian, [^\1]untuk benar-benar bekerja itu sulit. @ Mathiashansen - Anda lebih baik dengan yang berat dan mahal (?!\1).(jadi regex keseluruhan, dengan beberapa pembersihan efisiensi, akan (["'])(?:\\.|(?!\1).)*+\1. Ini +opsional jika mesin Anda tidak mendukungnya.
Adam Katz
2
Opsi yang belum pernah disentuh sebelumnya adalah:
Balikkan senar.
Lakukan pencocokan pada string terbalik.
Balikkan kembali string yang cocok.
Ini memiliki bonus tambahan karena mampu mencocokkan dengan benar tag terbuka yang lolos.
Katakanlah Anda memiliki string berikut; String \"this "should" NOT match\" and "this \"should\" match"
Di sini, \"this "should" NOT match\"tidak harus dicocokkan dan "should"harus. Di atas itu this \"should\" matchharus dicocokkan dan \"should\"tidak boleh.
Pertama, contoh.
// The input string.const myString ='String \\"this "should" NOT match\\" and "this \\"should\\" match"';// The RegExp.const regExp =newRegExp(// Match close'([\'"])(?!(?:[\\\\]{2})*[\\\\](?![\\\\]))'+'((?:'+// Match escaped close quote'(?:\\1(?=(?:[\\\\]{2})*[\\\\](?![\\\\])))|'+// Match everything thats not the close quote'(?:(?!\\1).)'+'){0,})'+// Match open'(\\1)(?!(?:[\\\\]{2})*[\\\\](?![\\\\]))','g');// Reverse the matched strings.
matches = myString
// Reverse the string..split('').reverse().join('')// '"hctam "\dluohs"\ siht" dna "\hctam TON "dluohs" siht"\ gnirtS'// Match the quoted.match(regExp)// ['"hctam "\dluohs"\ siht"', '"dluohs"']// Reverse the matches.map(x => x.split('').reverse().join(''))// ['"this \"should\" match"', '"should"']// Re order the matches.reverse();// ['"should"', '"this \"should\" match"']
Oke, sekarang untuk menjelaskan RegExp. Inilah regexp yang dapat dengan mudah dipecah menjadi tiga bagian. Sebagai berikut:
# Part 1(['"]) # Match a closing quotation mark " or '(?!# As long as it's not followed by(?:[\\]{2})*# A pair of escape characters[\\]# and a single escape(?![\\])# As long as that's not followed by an escape)# Part 2((?:# Match inside the quotes(?:# Match option 1:
\1 # Match the closing quote(?=# As long as it's followed by(?:\\\\)*# A pair of escape characters
\\ # (?![\\])# As long as that's not followed by an escape)# and a single escape)|# OR(?:# Match option 2:(?!\1).# Any character that isn't the closing quote))*)# Match the group 0 or more times# Part 3(\1)# Match an open quotation mark that is the same as the closing one(?!# As long as it's not followed by(?:[\\]{2})*# A pair of escape characters[\\]# and a single escape(?![\\])# As long as that's not followed by an escape)
Ini mungkin jauh lebih jelas dalam bentuk gambar: dihasilkan menggunakan Regulex Jex
Kita harus ingat bahwa regex bukanlah peluru perak untuk semua string-y. Beberapa hal lebih sederhana dilakukan dengan kursor dan linier, manual, mencari. Sebuah CFL akan melakukan trik cukup sepele, tetapi tidak ada banyak implementasi CFL (afaik).
Saya menghadapi masalah serupa saat mencoba menghapus string yang dikutip yang dapat mengganggu penguraian beberapa file.
Saya berakhir dengan solusi dua langkah yang mengalahkan regex berbelit-belit apa pun yang dapat Anda hasilkan:
line = line.replace("\\\"","\'");// Replace escaped quotes with something easier to handle
line = line.replaceAll("\"([^\"]*)\"","\"x\"");// Simple is beautiful
Jika IDE Anda adalah IntelliJ Idea, Anda bisa melupakan semua masalah ini dan menyimpan regex Anda ke dalam variabel String dan saat Anda menyalin-menempelkannya di dalam tanda kutip ganda, maka secara otomatis akan berubah ke format yang dapat diterima regex.
contoh di Jawa:
String s ="\"en_usa\":[^\\,\\}]+";
sekarang Anda dapat menggunakan variabel ini di regexp Anda atau di mana saja.
Jawaban:
Bekerja di The Regex Coach dan PCRE Workbench.
Contoh pengujian di JavaScript:
sumber
(?:...)
adalah kelompok pasif atau non-penangkap. Itu berarti tidak dapat direferensikan nanti./(["'])(?:[^\1\\]|\\.)*?\1/
var s = ' my \\"new\\" string and \"this should be matched\"';
, pendekatan ini akan membawa hasil yang tidak diharapkan.Yang ini berasal dari nanorc.sample yang tersedia di banyak distro linux. Ini digunakan untuk penyorotan sintaks dari string gaya C.
sumber
var s = ' my \\"new\\" string and \"this should be matched\"';
, pendekatan ini akan membawa hasil yang tidak diharapkan." \"(\\\\.|[^\\\"])*\" "
Seperti yang diberikan oleh ePharaoh, jawabannya adalah
Agar hal di atas berlaku untuk string kutip tunggal atau kutip ganda, gunakan
sumber
Sebagian besar solusi yang disediakan di sini menggunakan jalur pengulangan alternatif yaitu (A | B) *.
Anda mungkin mengalami stack overflows pada input yang besar karena beberapa compiler pola mengimplementasikannya menggunakan rekursi.
Java misalnya: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6337993
Sesuatu seperti ini:,
"(?:[^"\\]*(?:\\.)?)*"
atau yang disediakan oleh Guy Bedford akan mengurangi jumlah langkah penguraian untuk menghindari sebagian besar luapan tumpukan.sumber
Mengganti
\"
dan.
melewati tanda kutip lolos sementara pembilang malas*?
memastikan bahwa Anda tidak melewati akhir string yang dikutip. Bekerja dengan kelas .NET Framework REsumber
"\\"
var s = ' my \\"new\\" string and \"this should be matched\"';
/"(?:(?:\\"|[^"])*)"/g
ini harus diperbaikiDiambil langsung dari
man perlre
sistem Linux dengan Perl 5.22.0 diinstal. Sebagai pengoptimalan, ekspresi reguler ini menggunakan bentuk 'posesif' dari keduanya+
dan*
untuk mencegah mundur, karena telah diketahui sebelumnya bahwa string tanpa kutipan penutup tidak akan cocok dalam hal apa pun.sumber
harus bekerja dengan string yang dikutip
sumber
Yang ini berfungsi sempurna di PCRE dan tidak termasuk dalam StackOverflow.
Penjelasan:
"
;.*?
{Lazy match}; diakhiri dengan karakter non escape[^\\]
;(.*?[^\\])??
"
), tetapi bisa diawali dengan pasangan tanda escape nomor genap(\\\\)+
; dan itu adalah Greedy (!) opsional:((\\\\)+)?+
{Greedy matching}, string bacause bisa kosong atau tanpa pasangan penutup!sumber
"(.*?[^\\])?(\\\\)*"
ini adalah salah satu yang bekerja dengan "dan 'dan Anda dengan mudah menambahkan yang lain di awal.
itu menggunakan backreference (\ 1) yang sama persis dengan apa yang ada di grup pertama ("atau ').
http://www.regular-expressions.info/backref.html
sumber
[^\1]
harus diganti dengan.
karena tidak ada yang namanya anti-referensi-referensi, dan itu tidak masalah. kondisi pertama akan selalu cocok sebelum hal buruk bisa terjadi.[^\1]
dengan.
efektif akan mengubah regex ini untuk("|').*?\1
dan kemudian akan cocok"foo\"
di"foo \" bar"
. Meskipun demikian,[^\1]
untuk benar-benar bekerja itu sulit. @ Mathiashansen - Anda lebih baik dengan yang berat dan mahal(?!\1).
(jadi regex keseluruhan, dengan beberapa pembersihan efisiensi, akan(["'])(?:\\.|(?!\1).)*+\1
. Ini+
opsional jika mesin Anda tidak mendukungnya.Opsi yang belum pernah disentuh sebelumnya adalah:
Ini memiliki bonus tambahan karena mampu mencocokkan dengan benar tag terbuka yang lolos.
Katakanlah Anda memiliki string berikut;
String \"this "should" NOT match\" and "this \"should\" match"
Di sini,\"this "should" NOT match\"
tidak harus dicocokkan dan"should"
harus. Di atas ituthis \"should\" match
harus dicocokkan dan\"should\"
tidak boleh.Pertama, contoh.
Oke, sekarang untuk menjelaskan RegExp. Inilah regexp yang dapat dengan mudah dipecah menjadi tiga bagian. Sebagai berikut:
Ini mungkin jauh lebih jelas dalam bentuk gambar: dihasilkan menggunakan Regulex Jex
Gambar di github (JavaScript Regular Expression Visualizer.) Maaf, saya tidak memiliki reputasi yang cukup tinggi untuk menyertakan gambar, jadi, ini hanya tautan untuk saat ini.
Berikut adalah inti dari contoh fungsi yang menggunakan konsep ini yang sedikit lebih canggih: https://gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js
sumber
Kita harus ingat bahwa regex bukanlah peluru perak untuk semua string-y. Beberapa hal lebih sederhana dilakukan dengan kursor dan linier, manual, mencari. Sebuah CFL akan melakukan trik cukup sepele, tetapi tidak ada banyak implementasi CFL (afaik).
sumber
Versi yang lebih luas dari https://stackoverflow.com/a/10786066/1794894
Versi ini juga mengandung
“
dan tutup”
)sumber
Berantakan di regexpal dan berakhir dengan regex ini: (Jangan tanya saya cara kerjanya, saya hampir tidak mengerti bahkan ketika saya menulisnya lol)
sumber
Kalau dicari dari awal, mungkin bisa berhasil?
sumber
Saya menghadapi masalah serupa saat mencoba menghapus string yang dikutip yang dapat mengganggu penguraian beberapa file.
Saya berakhir dengan solusi dua langkah yang mengalahkan regex berbelit-belit apa pun yang dapat Anda hasilkan:
Lebih mudah dibaca dan mungkin lebih efisien.
sumber
Jika IDE Anda adalah IntelliJ Idea, Anda bisa melupakan semua masalah ini dan menyimpan regex Anda ke dalam variabel String dan saat Anda menyalin-menempelkannya di dalam tanda kutip ganda, maka secara otomatis akan berubah ke format yang dapat diterima regex.
contoh di Jawa:
sekarang Anda dapat menggunakan variabel ini di regexp Anda atau di mana saja.
sumber