Jawaban:
Saya telah menggunakan yang berikut ini dengan sangat sukses:
(["'])(?:(?=(\\?))\2.)*?\1
Ini mendukung kutipan bersarang juga.
Bagi mereka yang menginginkan penjelasan lebih dalam tentang bagaimana ini bekerja, berikut ini penjelasan dari pengguna singkat :
([""'])
cocok dengan kutipan;((?=(\\?))\2.)
jika garis miring terbalik ada, melahapnya, dan apakah itu terjadi atau tidak, cocok dengan karakter;*?
cocok berkali-kali (tidak rakus, untuk tidak makan kutipan penutup);\1
cocok dengan kutipan yang sama yang digunakan untuk pembukaan.
"foo\"
,. Trik pandangan ke depan membuat ?
kuantifier posesif (bahkan jika rasa regex tidak mendukung ?+
sintaksis atau pengelompokan atom)
(["'])(?:\\.|[^\\])*?\1
Secara umum, fragmen ekspresi reguler berikut adalah yang Anda cari:
"(.*?)"
Ini menggunakan * tidak serakah? Operator untuk menangkap semuanya hingga tetapi tidak termasuk penawaran ganda berikutnya. Kemudian, Anda menggunakan mekanisme khusus bahasa untuk mengekstrak teks yang cocok.
Dengan Python, Anda bisa melakukan:
>>> import re
>>> string = '"Foo Bar" "Another Value"'
>>> print re.findall(r'"(.*?)"', string)
['Foo Bar', 'Another Value']
"hello \" world"
"(.*?(?<!\\))"
Saya akan pergi untuk:
"([^"]*)"
The [^ "] adalah regex untuk setiap karakter kecuali ' " '
Alasan saya menggunakan ini selama non serakah banyak operator adalah bahwa saya harus terus mencari bahwa sampai hanya untuk memastikan aku mendapatkannya benar.
Mari kita lihat dua cara efisien yang berhubungan dengan kutipan yang lolos. Pola-pola ini tidak dirancang untuk ringkas atau estetika, tetapi untuk menjadi efisien.
Cara-cara ini menggunakan diskriminasi karakter pertama untuk dengan cepat menemukan kutipan dalam string tanpa biaya pergantian. (Idenya adalah membuang karakter yang bukan tanda kutip dengan cepat untuk menguji dua cabang dari pergantian.)
Konten di antara tanda kutip dijelaskan dengan loop yang tidak gulungan (alih-alih pergantian berulang) agar lebih efisien juga: [^"\\]*(?:\\.[^"\\]*)*
Tentunya untuk berurusan dengan string yang tidak menyeimbangkan kuotasi, Anda dapat menggunakan quantifiers posesif sebagai gantinya: [^"\\]*+(?:\\.[^"\\]*)*+
atau solusi untuk meniru mereka, untuk mencegah terlalu banyak mundur. Anda juga dapat memilih bahwa bagian yang dikutip dapat menjadi kutipan pembuka sampai kutipan berikutnya (tanpa pelarian) atau akhir dari string. Dalam hal ini tidak perlu menggunakan quantifiers posesif, Anda hanya perlu membuat kutipan terakhir opsional.
Perhatikan: terkadang kutipan tidak lolos dengan backslash tetapi dengan mengulangi kutipan. Dalam hal ini, subpola konten terlihat seperti ini:[^"]*(?:""[^"]*)*
Pola-pola tersebut menghindari penggunaan kelompok penangkap dan referensi balik (maksud saya kira-kira seperti (["']).....\1
) dan menggunakan pergantian sederhana tetapi dengan ["']
di awal, sebagai faktor.
Perl menyukai:
["'](?:(?<=")[^"\\]*(?s:\\.[^"\\]*)*"|(?<=')[^'\\]*(?s:\\.[^'\\]*)*')
(perhatikan bahwa (?s:...)
ini adalah sintaksis gula untuk mengaktifkan mode dotall / singleline di dalam grup yang tidak menangkap. Jika sintaks ini tidak didukung, Anda dapat dengan mudah mengaktifkan mode ini untuk semua pola atau mengganti dot dengan [\s\S]
)
(Cara pola ini ditulis benar-benar "digerakkan dengan tangan" dan tidak memperhitungkan optimasi internal mesin akhirnya)
Skrip ECMA:
(?=["'])(?:"[^"\\]*(?:\\[\s\S][^"\\]*)*"|'[^'\\]*(?:\\[\s\S][^'\\]*)*')
POSIX diperpanjang:
"[^"\\]*(\\(.|\n)[^"\\]*)*"|'[^'\\]*(\\(.|\n)[^'\\]*)*'
atau hanya:
"([^"\\]|\\.|\\\n)*"|'([^'\\]|\\.|\\\n)*'
/pattern/
tanpa melarikan diri apa pun (bukan notasi objek new RegExp("(?=[\"'])(?:\"[^\"\\\\]*...");
)
s
sini: (?s:
dan jika Anda menempatkan (?s)
suatu tempat dalam pola.
RegEx dari jawaban yang diterima mengembalikan nilai-nilai termasuk tanda kutip sourrounding mereka: "Foo Bar"
dan "Another Value"
sebagai cocok.
Berikut adalah RegEx yang hanya mengembalikan nilai antara tanda kutip (seperti yang ditanyakan oleh si penanya):
Hanya kutipan ganda (gunakan nilai capture group # 1):
"(.*?[^\\])"
Hanya kutipan tunggal (gunakan nilai capture group # 1):
'(.*?[^\\])'
Keduanya (gunakan nilai kelompok tangkap # 2):
(["'])(.*?[^\\])\1
-
Semua dukungan lolos dan kutipan bersarang.
src="(.*)"
tetapi jelas itu memilih segalanya sebelum yang terakhir ", REGEX Anda, meskipun, hanya memilih konten src =" ", tapi saya tidak mengerti bagaimana?
Secara khusus, tidak ada jawaban yang menghasilkan regex di mana kecocokan yang dikembalikan adalah teks di dalam tanda kutip, yang diminta. MA-Madden mencoba tetapi hanya mendapatkan pertandingan dalam sebagai kelompok yang ditangkap daripada seluruh pertandingan. Salah satu cara untuk melakukannya adalah:
(?<=(["']\b))(?:(?=(\\?))\2.)*?(?=\1)
Contoh untuk ini dapat dilihat di demo ini https://regex101.com/r/Hbj8aP/1
Kuncinya di sini adalah tampilan positif di belakang di awal (the ?<=
) dan tampilan positif di akhir (the ?=
). Lookbehind mencari di belakang karakter saat ini untuk memeriksa kutipan, jika ditemukan kemudian mulai dari sana dan kemudian lookahead memeriksa karakter di depan untuk kutipan dan jika ditemukan berhenti pada karakter itu. Grup lookbehind (the ["']
) dibungkus dengan tanda kurung untuk membuat grup untuk kutipan mana pun yang ditemukan di awal, ini kemudian digunakan di akhir lookahead (?=\1)
untuk memastikan itu hanya berhenti ketika menemukan kutipan yang sesuai.
Satu-satunya komplikasi lainnya adalah karena lookahead tidak benar-benar mengkonsumsi kutipan akhir, itu akan ditemukan lagi oleh tampilan awal di belakang yang menyebabkan teks antara akhir dan kutipan awal pada baris yang sama harus dicocokkan. Menempatkan batas kata pada kutipan pembuka ( ["']\b
) membantu dengan ini, meskipun idealnya saya ingin bergerak melewati lookahead tapi saya tidak berpikir itu mungkin. Bit yang memungkinkan karakter yang lolos di tengah saya ambil langsung dari jawaban Adam.
Pola di (["'])(?:(?=(\\?))\2.)*?\1
atas berhasil tetapi saya khawatir dengan kinerjanya (tidak buruk tapi bisa lebih baik). Milik saya di bawah ini ~ 20% lebih cepat.
Polanya "(.*?)"
tidak lengkap. Saran saya untuk semua orang yang membaca ini, JANGAN GUNAKANNYA !!!
Sebagai contoh, ia tidak dapat menangkap banyak string (jika perlu saya dapat memberikan test-case lengkap) seperti yang di bawah ini:
$ string = 'Bagaimana kabarmu? Saya
\'
baik-baik saja, terima kasih;
Sisanya sama baiknya dengan yang di atas.
Jika Anda benar-benar peduli dengan kinerja dan presisi, maka mulailah dengan yang berikut:
/(['"])((\\\1|.)*?)\1/gm
Dalam tes saya itu mencakup setiap string yang saya temui tetapi jika Anda menemukan sesuatu yang tidak berfungsi saya dengan senang hati akan memperbaruinya untuk Anda.
Saya menyukai solusi Eugen Mihailescu untuk mencocokkan konten antara tanda kutip sementara memungkinkan untuk melepaskan tanda kutip. Namun, saya menemukan beberapa masalah dengan melarikan diri dan muncul dengan regex berikut untuk memperbaikinya:
(['"])(?:(?!\1|\\).|\\.)*\1
Ia melakukan trik dan masih cukup sederhana dan mudah dirawat.
Demo (dengan beberapa lagi kasus uji; jangan ragu untuk menggunakannya dan mengembangkannya).
PS: Jika Anda hanya ingin konten di antara kutipan dalam pertandingan penuh ( $0
), dan tidak takut dengan penggunaan penalti kinerja:
(?<=(['"])\b)(?:(?!\1|\\).|\\.)*(?=\1)
Sayangnya, tanpa tanda kutip sebagai jangkar, saya harus menambahkan batas \b
yang tidak cocok dengan spasi dan karakter batas non-kata setelah kutipan awal.
Atau, modifikasi versi awal hanya dengan menambahkan grup dan ekstrak bentuk string$2
:
(['"])((?:(?!\1|\\).|\\.)*)\1
PPS: Jika fokus Anda hanya pada efisiensi, gunakan solusi Casimir et Hippolyte ; itu bagus.
-
, seperti dalam koordinat bujur.
Versi ini
mengontrol mundur
/(["'])((?:(?!\1)[^\\]|(?:\\\\)*\\[^\\])*)\1/
LEBIH JAWABAN! Inilah solusi yang saya gunakan
\"([^\"]*?icon[^\"]*?)\"
TLDR;
ganti ikon kata dengan apa yang Anda cari dalam kutipan kata dan voila!
Cara kerjanya adalah mencari kata kunci dan tidak peduli apa lagi di antara tanda kutip. EG:
id="fb-icon"
id="icon-close"
id="large-icon-close"
regex mencari tanda kutip "
kemudian mencari kemungkinan sekelompok huruf yang tidak "
sampai ia menemukan icon
dan setiap kelompok huruf yang mungkin bukan "
kemudian mencari penutup"
name="value"
dengan name={"value"}
karena regex jawaban ini kembali icon
/ value
sebagai kelompok kedua (tidak seperti jawaban yang diterima). Cari : =\"([^\"]*?[^\"]*?)\"
Ganti :={"$1"}
Saya menyukai versi yang lebih luas dari Axeman, tetapi memiliki beberapa masalah dengan itu (itu tidak cocok misalnya
foo "string \\ string" bar
atau
foo "string1" bar "string2"
dengan benar, jadi saya mencoba memperbaikinya:
# opening quote
(["'])
(
# repeat (non-greedy, so we don't span multiple strings)
(?:
# anything, except not the opening quote, and not
# a backslash, which are handled separately.
(?!\1)[^\\]
|
# consume any double backslash (unnecessary?)
(?:\\\\)*
|
# Allow backslash to escape characters
\\.
)*?
)
# same character as opening quote
\1
string = "\" foo bar\" \"loloo\""
print re.findall(r'"(.*?)"',string)
coba saja ini, bekerja seperti pesona !!!
\
menunjukkan melewatkan karakter
" foo bar" "loloo"
. Saya menduga Anda dimaksudkan untuk membungkus bahwa dalam string mentah seperti yang Anda lakukan dengan regex: r'"\" foo bar\" \"loloo\""'
. Silakan manfaatkan kemampuan pemformatan SO yang sangat baik kapan saja sesuai. Bukan hanya kosmetik; kami benar-benar tidak tahu apa yang ingin Anda katakan jika Anda tidak menggunakannya. Dan selamat datang di Stack Overflow !
echo 'junk "Foo Bar" not empty one "" this "but this" and this neither' | sed 's/[^\"]*\"\([^\"]*\)\"[^\"]*/>\1</g'
Ini akan menghasilkan:> Foo Bar <> <> tetapi ini <
Di sini saya menunjukkan hasil string antara> <'s untuk kejelasan, juga menggunakan versi non-serakah dengan perintah sed ini pertama-tama kita membuang sampah sebelum dan sesudah itu "" dan kemudian ganti ini dengan bagian antara "" dan lewati ini dengan> <'s.
Dari Greg H. Saya dapat membuat regex ini sesuai dengan kebutuhan saya.
Saya harus mencocokkan nilai tertentu yang memenuhi syarat dengan menjadi kutipan di dalam. Itu harus pertandingan penuh, tidak ada pencocokan parsial yang dapat memicu klik
mis. "test" tidak cocok untuk "test2".
reg = r"""(['"])(%s)\1"""
if re.search(reg%(needle), haystack, re.IGNORECASE):
print "winning..."
Pemburu
Jika Anda mencoba menemukan string yang hanya memiliki akhiran tertentu, seperti sintaksis titik, Anda dapat mencoba ini:
\"([^\"]*?[^\"]*?)\".localized
Di mana .localized
suffix.
Contoh:
print("this is something I need to return".localized + "so is this".localized + "but this is not")
Itu akan menangkap "this is something I need to return".localized
dan "so is this".localized
tetapi tidak "but this is not"
.
Jawaban tambahan untuk subset coders Microsoft VBA hanya satu yang menggunakan perpustakaan Microsoft VBScript Regular Expressions 5.5
dan ini memberikan kode berikut
Sub TestRegularExpression()
Dim oRE As VBScript_RegExp_55.RegExp '* Tools->References: Microsoft VBScript Regular Expressions 5.5
Set oRE = New VBScript_RegExp_55.RegExp
oRE.Pattern = """([^""]*)"""
oRE.Global = True
Dim sTest As String
sTest = """Foo Bar"" ""Another Value"" something else"
Debug.Assert oRE.test(sTest)
Dim oMatchCol As VBScript_RegExp_55.MatchCollection
Set oMatchCol = oRE.Execute(sTest)
Debug.Assert oMatchCol.Count = 2
Dim oMatch As Match
For Each oMatch In oMatchCol
Debug.Print oMatch.SubMatches(0)
Next oMatch
End Sub
Bagi saya yang bekerja ini:
|([\'"])(.*?)\1|i
Saya telah menggunakan kalimat seperti ini:
preg_match_all('|([\'"])(.*?)\1|i', $cont, $matches);
dan itu bekerja dengan baik.
Semua jawaban di atas adalah baik .... kecuali mereka TIDAK mendukung semua karakter unicode! di ECMA Script (Javascript)
Jika Anda adalah pengguna Node, Anda mungkin menginginkan versi modifikasi dari jawaban yang diterima yang mendukung semua karakter unicode:
/(?<=((?<=[\s,.:;"']|^)["']))(?:(?=(\\?))\2.)*?(?=\1)/gmu
Coba di sini .
? The preceding token is not quantifiable