回答:
私は以下を使用して大きな成功を収めています:
(["'])(?:(?=(\\?))\2.)*?\1
ネストされた引用符もサポートしています。
これがどのように機能するかについてより深い説明が必要な人のために、ユーザーephemientからの説明があります:
([""'])
引用と一致;((?=(\\?))\2.)
バックスラッシュが存在する場合は、それをぐちゃぐちゃにし、それが発生するかどうかに関係なく、文字に一致させます。*?
何度も一致します(貪欲ではなく、終了の引用を食べません)。\1
オープニングに使用されたのと同じ見積もりと一致します。
"foo\"
ます。先読みのトリックにより、?
量指定子が所有権を持つようになります(正規表現フレーバーが?+
構文またはアトミックグループ化をサポートしていない場合でも)
(["'])(?:\\.|[^\\])*?\1
一般的に、次の正規表現の断片はあなたが探しているものです:
"(.*?)"
これは貪欲ではない*?次の二重引用符を除くすべてをキャプチャする演算子。次に、言語固有のメカニズムを使用して、一致したテキストを抽出します。
Pythonでは、次のことができます。
>>> import re
>>> string = '"Foo Bar" "Another Value"'
>>> print re.findall(r'"(.*?)"', string)
['Foo Bar', 'Another Value']
"hello \" world"
"(.*?(?<!\\))"
私は行きます:
"([^"]*)"
[^「]以外の任意の文字のための正規表現は' 」 "
私は非欲張り多くのオペレータの上にこれを使用する理由は、私は念の私はそれが正しい取得するためにそれを探し続ける必要があるということです。
エスケープされた引用符を処理する2つの効率的な方法を見てみましょう。これらのパターンは、簡潔でも美的でもないように設計されていますが、効率的です。
これらの方法では、最初の文字の識別を使用して、代替のコストなしで文字列内の引用符をすばやく検索します。(アイデアは、交互の2つのブランチをテストせずに、引用符ではない文字をすばやく破棄することです。)
引用符間のコンテンツは、より効率的になるように(繰り返しの代わりに)展開されたループで記述されます。 [^"\\]*(?:\\.[^"\\]*)*
明らかに引用符のバランスが取れていない文字列を処理する場合は、代わりに所有格指定子を使用する[^"\\]*+(?:\\.[^"\\]*)*+
か、過度のバックトラックを防ぐためにそれらをエミュレートする回避策を使用できます。次の(エスケープされていない)引用符または文字列の終わりまで、引用符で囲まれた部分を開始引用符にすることもできます。この場合、所有格指定子を使用する必要はありません。最後の引用符をオプションにするだけで済みます。
注意:引用符はバックスラッシュでエスケープされない場合がありますが、引用符を繰り返すことによりエスケープされます。この場合、コンテンツサブパターンは次のようになります。[^"]*(?:""[^"]*)*
パターンは、キャプチャグループと後方参照((["']).....\1
たとえばのようなもの)の使用を避け、単純な代替を使用しますが["']
、最初は重要です。
Perlのような:
["'](?:(?<=")[^"\\]*(?s:\\.[^"\\]*)*"|(?<=')[^'\\]*(?s:\\.[^'\\]*)*')
(これ(?s:...)
は非キャプチャグループ内のdotall / singlelineモードをオンにする構文上の砂糖です。この構文がサポートされていない場合は、すべてのパターンでこのモードをオンにするか、ドットをで置き換えることができます[\s\S]
)
(このパターンの記述方法は完全に「手動」であり、最終的なエンジン内部の最適化は考慮されていません)
ECMAスクリプト:
(?=["'])(?:"[^"\\]*(?:\\[\s\S][^"\\]*)*"|'[^'\\]*(?:\\[\s\S][^'\\]*)*')
拡張されたPOSIX:
"[^"\\]*(\\(.|\n)[^"\\]*)*"|'[^'\\]*(\\(.|\n)[^'\\]*)*'
または単に:
"([^"\\]|\\.|\\\n)*"|'([^'\\]|\\.|\\\n)*'
/pattern/
エスケープせずにリテラル表記を使用するだけでよいことに注意してください(オブジェクト表記ではなくnew RegExp("(?=[\"'])(?:\"[^\"\\\\]*...");
)
s
here:を削除して、パターンのどこかに(?s:
置くと、Perlバージョンを使用できます(?s)
。
受け入れ答えの正規表現は、そのsourroundingの引用符を含む値を返します"Foo Bar"
し、"Another Value"
試合など。
引用符で囲まれた値のみを返すRegExは次のとおりです(質問者が要求したとおり)。
二重引用符のみ(キャプチャグループ#1の値を使用):
"(.*?[^\\])"
単一引用符のみ(キャプチャグループ#1の値を使用):
'(.*?[^\\])'
両方(キャプチャグループ#2の値を使用):
(["'])(.*?[^\\])\1
-
エスケープおよびネストされた引用符をすべてサポートします。
src="(.*)"
が、最後の『内容」をお使いの正規表現は、しかし、=のみSRCを選択し、』前に明らかにそれはすべてを選択しましたが、私は理解していなかったか?
特に、これらの回答はいずれも、返される一致が引用符内のテキストである正規表現を生成しません。MA-Maddenは、マッチ全体ではなく、キャプチャされたグループとして内部一致のみを取得しようとします。実際にそれを行う1つの方法は次のとおりです。
(?<=(["']\b))(?:(?=(\\?))\2.)*?(?=\1)
この例は、このデモhttps://regex101.com/r/Hbj8aP/1で見ることができます
ここで重要なのは、開始時?<=
の肯定的な先読み()と終了時の肯定的な先読み(?=
)です。後読みは現在の文字の後ろを調べて引用をチェックします。見つかった場合はそこから開始し、先読みは引用の前の文字をチェックし、見つかった場合はその文字で停止します。後読みグループ(["']
)は括弧で囲まれて、最初に見つかった引用のグループを作成します。これは最後の先読みで使用され(?=\1)
、対応する引用が見つかったときにのみ停止するようにします。
他の唯一の複雑な点は、先読みが実際に終了引用符を消費しないため、同じ行の終了引用符と開始引用符の間のテキストが一致する原因となる開始後読みによって再び検出されることです。冒頭の引用(["']\b
)に単語の境界を付けると、これに役立ちますが、先読みを超えて移動したいのですが、可能ではないと思います。途中でエスケープされたキャラクターを許可するビットは、アダムの答えから直接取っています。
上記のパターン(["'])(?:(?=(\\?))\2.)*?\1
はうまくいきますが、私はそのパフォーマンスを心配しています(悪くはありませんが、もっと良いかもしれません)。その下の鉱山は約20%高速です。
パターン"(.*?)"
は不完全です。これを読んでいる皆への私のアドバイスはただそれを使用しないでください!!!
たとえば、以下のような多くの文字列をキャプチャすることはできません(必要に応じて、徹底的なテストケースを提供できます)。
$ string = 'お元気ですか?私は
\'
「ありがとう、罰金をmは、
それらの残りは上記のものと同じように「良い」です。
パフォーマンスと精度の両方を本当に重視する場合は、次のいずれかから始めます。
/(['"])((\\\1|.)*?)\1/gm
私のテストでは、出会ったすべての文字列をカバーしましたが、機能しないものが見つかった場合は、喜んで更新します。
私は、引用符をエスケープしながら、引用符の間のコンテンツを一致させるEugen Mihailescuのソリューションが好きでした。しかし、エスケープに関するいくつかの問題を発見し、それらを修正するために次の正規表現を思いつきました:
(['"])(?:(?!\1|\\).|\\.)*\1
それはトリックを行い、それでもかなりシンプルでメンテナンスが簡単です。
デモ(いくつかのテストケースがあります。自由に使用して拡張してください)。
PS:完全一致()の引用符で囲まれたコンテンツが必要$0
で、パフォーマンスの低下を恐れない場合:
(?<=(['"])\b)(?:(?!\1|\\).|\\.)*(?=\1)
残念ながら、アンカーとしての引用符\b
がないと、開始引用符の後にスペースや単語以外の境界文字でうまく機能しない境界を追加する必要がありました。
または、単にグループを$2
追加して初期バージョンを変更し、文字列形式を抽出します。
(['"])((?:(?!\1|\\).|\\.)*)\1
PPS:効率のみを重視する場合は、Casimir et Hippolyteのソリューションを使用してください。それは良いものです。
-
経度座標の場合のように、マイナス記号の付いた値を見逃します。
このバージョン
バックトラックを制御する
/(["'])((?:(?!\1)[^\\]|(?:\\\\)*\\[^\\])*)\1/
もっと回答!これが私が使った解決策です
\"([^\"]*?icon[^\"]*?)\"
TLDR;
単語のアイコンをあなたが言った引用と出来上がりで探しているものに置き換えてください!
これが機能する方法は、キーワードを検索し、引用符の間にある他の何も気にしないことです。EG:
id="fb-icon"
id="icon-close"
id="large-icon-close"
正規表現は引用符を"
探し、次にそれが"
見つかるまで存在icon
しない可能性のある文字のグループを探し、それ以外の可能性のある文字のグループは"
終わりを探します"
name="value"
をすべてので置き換えることができました。検索:置換:name={"value"}
icon
value
=\"([^\"]*?[^\"]*?)\"
={"$1"}
私はAxemanのより拡張されたバージョンが好きでしたが、それに問題がありました(たとえば、一致しませんでした)
foo "string \\ string" bar
または
foo "string1" bar "string2"
正しく、私はそれを修正しようとしました:
# 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)
これを試してみてください、魅力のように動作します!!!
\
スキップ文字を示します
" foo bar" "loloo"
。正規表現で行ったように、それを生の文字列でラップするつもりだったと思います:r'"\" foo bar\" \"loloo\""'
。必要に応じて、SOの優れたフォーマット機能を利用してください。化粧品だけではありません。それらを使用しないと、文字通りあなたは何を言おうとしているのかを知ることができません。そして、Stack Overflowへようこそ!
ドット構文など、特定のサフィックスのみが付いた文字列を検索する場合は、次のように試すことができます。
\"([^\"]*?[^\"]*?)\".localized
どこ .localized
接尾辞は。
例:
print("this is something I need to return".localized + "so is this".localized + "but this is not")
キャプチャ"this is something I need to return".localized
します"so is this".localized
が、キャプチャしません"but this is not"
。
Microsoft VBAコーダーのサブセットに対する補足的な回答は、ライブラリMicrosoft VBScript Regular Expressions 5.5
を1つだけ使用し、これは次のコードを提供します
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
私にとってこれを働いた:
|([\'"])(.*?)\1|i
私はこのような文で使用しました:
preg_match_all('|([\'"])(.*?)\1|i', $cont, $matches);
そしてそれは素晴らしく機能しました。
上記のすべての答えは良いです... すべてのユニコード文字をサポートしていないことを除いて!ECMAスクリプト(Javascript)
Nodeユーザーの場合は、すべてのUnicode文字をサポートする承認された回答の修正バージョンが必要になる場合があります。
/(?<=((?<=[\s,.:;"']|^)["']))(?:(?=(\\?))\2.)*?(?=\1)/gmu
? The preceding token is not quantifiable