Bagaimana cara mendapatkan substring " It's big \"problem "
menggunakan ekspresi reguler?
s = ' function(){ return " It\'s big \"problem "; }';
Bagaimana cara mendapatkan substring " It's big \"problem "
menggunakan ekspresi reguler?
s = ' function(){ return " It\'s big \"problem "; }';
Jawaban:
/"(?:[^"\\]|\\.)*"/
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);
(?:...)
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.
\"(\\.|[^\"])*\"
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
/"([^"\\]*(\\.[^"\\]*)*)"|\'([^\'\\]*(\\.[^\'\\]*)*)\'/
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.
/"(?:[^"\\]++|\\.)*+"/
Diambil 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.
/(["\']).*?(?<!\\)(\\\\)*\1/is
harus bekerja dengan string yang dikutip
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!"(.*?[^\\])?(\\\\)*"
ini adalah salah satu yang bekerja dengan "dan 'dan Anda dengan mudah menambahkan yang lain di awal.
("| ') (?: \\\ 1 | [^ \ 1]) *? \ 1
itu menggunakan backreference (\ 1) yang sama persis dengan apa yang ada di grup pertama ("atau ').
[^\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 itu this \"should\" match
harus 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 = new RegExp(
// 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
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
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).
Versi yang lebih luas dari https://stackoverflow.com/a/10786066/1794894
/"([^"\\]{50,}(\\.[^"\\]*)*)"|\'[^\'\\]{50,}(\\.[^\'\\]*)*\'|“[^”\\]{50,}(\\.[^“\\]*)*”/
Versi ini juga mengandung
“
dan tutup ”
)Berantakan di regexpal dan berakhir dengan regex ini: (Jangan tanya saya cara kerjanya, saya hampir tidak mengerti bahkan ketika saya menulisnya lol)
"(([^"\\]?(\\\\)?)|(\\")+)+"
Kalau dicari dari awal, mungkin bisa berhasil?
\"((\\\")|[^\\])*\"
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
Lebih mudah dibaca dan mungkin lebih efisien.
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.