Yanıtlar:
Aşağıdakileri büyük bir başarıyla kullanıyorum:
(["'])(?:(?=(\\?))\2.)*?\1
İç içe tırnakları da destekler.
Bunun nasıl çalıştığına dair daha ayrıntılı bir açıklama yapmak isteyenler için, kullanıcı ephemient'inden bir açıklama :
([""'])
bir teklifle eşleşir;((?=(\\?))\2.)
ters eğik çizgi varsa, silip süpürün ve bunun olup olmadığını bir karakterle eşleştirin;*?
birçok kez eşleşir (açgözlülükle, kapanış teklifini yememek için);\1
açılış için kullanılan aynı teklif ile eşleşir.
"foo\"
. İleriye bakma hilesi, ?
nicelleştiriciyi sahipleniyor (regex lezzeti ?+
sözdizimini veya atom gruplamasını desteklemese bile )
(["'])(?:\\.|[^\\])*?\1
Genel olarak, aşağıdaki düzenli ifade parçası aradığınız şeydir:
"(.*?)"
Bu açgözlü olmayan * kullanır? Operatör bir sonraki çift tırnak dahil olmak üzere kadar her şeyi yakalamak için. Ardından, eşleşen metni ayıklamak için dile özgü bir mekanizma kullanırsınız.
Python'da şunları yapabilirsiniz:
>>> import re
>>> string = '"Foo Bar" "Another Value"'
>>> print re.findall(r'"(.*?)"', string)
['Foo Bar', 'Another Value']
"hello \" world"
"(.*?(?<!\\))"
Ben giderdim:
"([^"]*)"
[^ "] Dışında herhangi karakter için düzenli ifade olan ' " '
ı olmayan açgözlü birçok operatör üzerinden bu kullanmak nedenle sadece emin bunu düzeltmek olsun yapmak için o kadar aramaya devam etmek zorunda olmasıdır.
Kaçan alıntılarla başa çıkmanın iki etkili yolunu görelim. Bu kalıplar kısa ve estetik olarak değil, verimli olacak şekilde tasarlanmıştır.
Bu yollar, bir alternatifin maliyeti olmadan dizede tırnak işaretleri bulmak için ilk karakter ayrımını kullanır. (Fikir, değişimin iki dalını test etmeden tırnak işareti olmayan karakterleri hızlı bir şekilde atmaktır.)
Teklifler arasındaki içerik, daha verimli olması için kaydedilmemiş bir döngü (tekrarlanan bir dönüşüm yerine) ile açıklanır: [^"\\]*(?:\\.[^"\\]*)*
Açıkça dengeli tırnak işareti olmayan dizelerle uğraşmak için, bunun yerine iyelik niceleyicileri kullanabilirsiniz: [^"\\]*+(?:\\.[^"\\]*)*+
ya da çok fazla geri izlemeyi önlemek için bunları taklit etmek için bir geçici çözüm. Alıntılanan bir parçanın bir sonraki (kaçan olmayan) alıntıya veya dizenin sonuna kadar bir açılış alıntısı olmasını da seçebilirsiniz. Bu durumda, iyelik niceliklerini kullanmaya gerek yoktur, sadece son alıntıyı isteğe bağlı yapmanız gerekir.
Uyarı: bazen tırnak işaretleri ters eğik çizgi ile değil, tekrarı tekrarlayarak kaçar. Bu durumda, içerik alt deseni şöyle görünür:[^"]*(?:""[^"]*)*
Modeller bir yakalama grubunun ve bir geri başvurunun kullanılmasını önler (yani bir şey demek istiyorum (["']).....\1
) ve basit bir değişim kullanır, ancak ["']
başlangıçta faktörle birlikte.
Perl gibi:
["'](?:(?<=")[^"\\]*(?s:\\.[^"\\]*)*"|(?<=')[^'\\]*(?s:\\.[^'\\]*)*')
( (?s:...)
yakalamayan grup içinde dotall / singleline modunu açmak için sözdizimsel bir şeker olduğuna dikkat edin . Bu sözdizimi desteklenmiyorsa, tüm desen için bu modu kolayca açabilir veya noktayı değiştirebilirsiniz [\s\S]
)
(Bu kalıbın yazılma şekli tamamen "elle çalıştırılır" ve nihai motor dahili optimizasyonlarını dikkate almaz)
ECMA betiği:
(?=["'])(?:"[^"\\]*(?:\\[\s\S][^"\\]*)*"|'[^'\\]*(?:\\[\s\S][^'\\]*)*')
POSIX genişletildi:
"[^"\\]*(\\(.|\n)[^"\\]*)*"|'[^'\\]*(\\(.|\n)[^'\\]*)*'
ya da sadece:
"([^"\\]|\\.|\\\n)*"|'([^'\\]|\\.|\\\n)*'
/pattern/
(yerine nesne gösterimi bir şey kaçan olmadan new RegExp("(?=[\"'])(?:\"[^\"\\\\]*...");
)
s
burada kaldırırsanız ve desende bir yere (?s:
koyarsanız Perl sürümünü kullanabilirsiniz (?s)
.
Kabul edilen yanıtın RegEx değeri, ek tırnak işaretleri: "Foo Bar"
ve "Another Value"
eşleşmeler olarak dahil değerleri döndürür .
Yalnızca tırnak işaretleri arasındaki değerleri döndüren (sorgulayıcının istediği gibi) RegEx şunlardır :
Yalnızca çift tırnak (1 numaralı yakalama grubunun değerini kullanın):
"(.*?[^\\])"
Yalnızca tek tırnak (1 numaralı yakalama grubunun değerini kullanın):
'(.*?[^\\])'
Her ikisi de (yakalama grubu # 2 değerini kullanın):
(["'])(.*?[^\\])\1
-
Tüm destek kaçtı ve iç içe tırnak.
src="(.*)"
ama geçen 'içeriği" senin REGEX, olsa da, = yalnızca src seçilen' önce belli ki her şeyi seçerek, ama ben anlamadım nasıl?
Tuhaf bir şekilde, bu cevapların hiçbiri, döndürülen eşleşmenin tırnak içindeki metin olduğu regex üretmez, bu da istenir. MA-Madden dener, ancak iç maçı tüm maçtan ziyade yakalanan bir grup olarak alır. Aslında bunu yapmanın bir yolu:
(?<=(["']\b))(?:(?=(\\?))\2.)*?(?=\1)
Bunun örnekleri bu demoda görülebilir https://regex101.com/r/Hbj8aP/1
Buradaki anahtar, başlangıçtaki ?<=
pozitif bakış açısı (the ) ve sondaki pozitif bakış açısı (the ?=
). Gözetleme, bir teklif olup olmadığını kontrol etmek için mevcut karakterin arkasına bakıyor, eğer o zaman oradan başlayın ve sonra ileriye doğru bir teklif için karakteri kontrol ediyor ve bulunursa o karakterde duruyor. Yeniden inceleme grubu ( ["']
), başlangıçta hangi alıntı bulunduğuna ilişkin bir grup oluşturmak için parantez içine alınır, bu daha sonra (?=\1)
yalnızca ilgili alıntıyı bulduğunda durduğundan emin olmak için sonunda ileriye doğru kullanılır .
Diğer tek sorun, ileriye doğru son alıntıyı kullanmadığı için, aynı satırdaki bitiş ve başlangıç tırnakları arasındaki metnin eşleşmesine neden olan başlangıç bakış arkası tarafından tekrar bulunacaktır. ["']\b
İdeal olarak, ileriye doğru ilerlemek istiyorum, ancak bunun mümkün olduğunu düşünmüyorum, ancak açılış teklifine ( ) bir kelime sınırı koymak bu konuda yardımcı olur. Ortadaki kaçan karakterlere izin veren biraz, doğrudan Adam'ın cevabından aldım.
Yukarıdaki desen (["'])(?:(?=(\\?))\2.)*?\1
işi yapıyor ancak performanslarından endişeliyim (kötü değil ama daha iyi olabilir). Benimki ~% 20 daha hızlı.
Desen "(.*?)"
tamamlanmadı. Bu okuma herkes için benim tavsiyem sadece KULLANMAYIN !!!
Örneğin, aşağıdaki gibi birçok dizeyi yakalayamaz (gerekirse kapsamlı bir test durumu sağlayabilirim):
$ string = 'Nasılsın? Ben
\'
iyiyim, teşekkür ederim ';
Geri kalanı da yukarıdaki gibi "iyi" dir.
Hem performansı hem de hassasiyeti gerçekten önemsiyorsanız, aşağıdaki ile başlayın:
/(['"])((\\\1|.)*?)\1/gm
Testlerimde tanıştığım her dizeyi kapsıyordu, ancak işe yaramayan bir şey bulursanız memnuniyetle sizin için güncelleyeceğim.
Eugen Mihailescu'nun tırnak işaretleri arasındaki içeriğe uygun çözümünü , tırnaklardan kaçmaya izin verirken beğendim . Ancak, kaçmakla ilgili bazı problemler keşfettim ve bunları düzeltmek için aşağıdaki normal ifadeyi buldum:
(['"])(?:(?!\1|\\).|\\.)*\1
Hile yapar ve hala oldukça basit ve bakımı kolaydır.
Demo (bazı test senaryolarıyla; kullanmaktan ve genişletmekten çekinmeyin).
Not: Sadece içerik istiyorsanız arasındaki tam maçında (içinde tırnak $0
) ve performans cezası kullanım korkmuyoruz:
(?<=(['"])\b)(?:(?!\1|\\).|\\.)*(?=\1)
Ne yazık ki, tırnakları tırnaklar olmadan \b
, başlangıç alıntısından sonra boşluklarla ve sözcük olmayan sınır karakterleriyle iyi oynamayan bir sınır eklemek zorunda kaldım .
Alternatif olarak, bir grup$2
ekleyerek ilk sürümü değiştirin ve dize formunu çıkarın :
(['"])((?:(?!\1|\\).|\\.)*)\1
PPS: Odak noktanız sadece verimlilik üzerindeyse, Casimir et Hippolyte'nin çözümüyle devam edin ; iyi bir tane.
-
, boylam koordinatlarında olduğu gibi eksi işaretli bir değeri kaçırır .
Bu versiyon
geri izlemeyi kontrol eder
/(["'])((?:(?!\1)[^\\]|(?:\\\\)*\\[^\\])*)\1/
DAHA CEVAPLAR! İşte kullandığım çözüm
\"([^\"]*?icon[^\"]*?)\"
TLDR;
kelime simgesi yerine tırnak ve voila içinde aradığınız ile değiştirin !
Bu şekilde çalışır, anahtar kelime arar ve tırnak işaretleri arasında başka bir şey umurumda değil. EG:
id="fb-icon"
id="icon-close"
id="large-icon-close"
normal ifade bir teklif işareti "
arar
ve "
bulana kadar olası herhangi bir harf grubunu arar icon
ve olmayan herhangi bir olası harf grubunu "
arar."
name="value"
ile name={"value"}
bu cevabım regex getiriler beri icon
/ value
(kabul yanıt aksine) ikinci grup olarak. Bul : =\"([^\"]*?[^\"]*?)\"
Değiştir :={"$1"}
Axeman'ın daha geniş versiyonunu beğendim, ancak bununla ilgili bir sorun yaşadım (örneğin eşleşmedi)
foo "string \\ string" bar
veya
foo "string1" bar "string2"
doğru, bu yüzden düzeltmeye çalıştım:
# 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)
sadece bunu deneyin, bir cazibe gibi çalışır !!!
\
atlama karakterini gösterir
" foo bar" "loloo"
. Ben size regex ile yaptığı gibi bir ham dizede o sarmak içindir şüpheli: r'"\" foo bar\" \"loloo\""'
. Lütfen uygun olduğunda SO'nun mükemmel biçimlendirme özelliklerini kullanın . Sadece kozmetik değil; bunları kullanmazsanız ne söylemeye çalıştığınızı tam olarak söyleyemeyiz. Ve Stack Overflow'a hoş geldiniz !
echo 'junk "Foo Bar" not empty one "" this "but this" and this neither' | sed 's/[^\"]*\"\([^\"]*\)\"[^\"]*/>\1</g'
Bunun sonucu:> Foo Bar <> <> ama bu <
Burada netlik için> <'s arasındaki sonuç dizesini gösterdim, ayrıca bu sed komutuyla açgözlü olmayan sürümü kullanarak önce ""' den önce ve sonra önemsizleri atıyoruz ve bunu "" arasındaki parçayla değiştiriyoruz. 've bunu> <' s ile çevreleyin.
Greg H.'den bu regex'i ihtiyaçlarımı karşılayabildim.
Tekliflerin içinde kalarak nitelendirilen belirli bir değeri eşleştirmem gerekiyordu. Tam bir eşleşme olmalı, hiçbir kısmi eşleşme isabeti tetikleyemez
örneğin "test", "test2" ile eşleşemedi.
reg = r"""(['"])(%s)\1"""
if re.search(reg%(needle), haystack, re.IGNORECASE):
print "winning..."
avcı
Nokta sözdizimi gibi yalnızca belirli bir son eki olan dizeleri bulmaya çalışıyorsanız, bunu deneyebilirsiniz:
\"([^\"]*?[^\"]*?)\".localized
Son .localized
ek nerede ?
Misal:
print("this is something I need to return".localized + "so is this".localized + "but this is not")
Yakalayacak "this is something I need to return".localized
ve "so is this".localized
olmayacak "but this is not"
.
Microsoft VBA kodlayıcılarının alt kümesi için ek bir yanıt kitaplığı kullanır Microsoft VBScript Regular Expressions 5.5
ve bu aşağıdaki kodu verir
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
Benim için bu çalıştı:
|([\'"])(.*?)\1|i
Bunun gibi bir cümlede kullandım:
preg_match_all('|([\'"])(.*?)\1|i', $cont, $matches);
ve harika çalıştı.
Yukarıdaki tüm cevaplar iyidir .... hariç tüm unicode karakterleri desteklemez! ECMA Script'te (Javascript)
Düğüm kullanıcısıysanız, kabul edilen yanıtın tüm unicode karakterleri destekleyen değiştirilmiş sürümünü isteyebilirsiniz:
/(?<=((?<=[\s,.:;"']|^)["']))(?:(?=(\\?))\2.)*?(?=\1)/gmu
Burada deneyin .
? The preceding token is not quantifiable