web-dev-qa-db-ja.com

引用符をエスケープする引用符付き文字列の正規表現

正規表現を使用してサブストリング" It's big \"problem "を取得するにはどうすればよいですか?

s = ' function(){  return " It\'s big \"problem  ";  }';     
110
Andrii Kasian
/"(?:[^"\\]|\\.)*"/

The Regex CoachおよびPCRE Workbenchで動作します。

JavaScriptでのテストの例:

    var s = ' function(){ return " Is big \\"problem\\", \\no? "; }';
    var m = s.match(/"(?:[^"\\]|\\.)*"/);
    if (m != null)
        alert(m);
133
PhiLho

これは、多くのLinuxディストリビューションで利用可能なnanorc.sampleからのものです。 Cスタイル文字列の構文強調表示に使用されます

\"(\\.|[^\"])*\"
28
Darrell

EPharaohが提供するように、答えは

/"([^"\\]*(\\.[^"\\]*)*)"/

上記を単一引用符または二重引用符で囲まれた文字列に適用するには、次を使用します

/"([^"\\]*(\\.[^"\\]*)*)"|\'([^\'\\]*(\\.[^\'\\]*)*)\'/
15
Guy Bedford

ここで提供されるソリューションのほとんどは、代替繰り返しパス、つまり(A | B)*を使用します。

一部のパターンコンパイラは再帰を使用してこれを実装するため、大きな入力でスタックオーバーフローが発生する場合があります。

たとえば、Java: http://bugs.Java.com/bugdatabase/view_bug.do?bug_id=633799

次のようなもの:"(?:[^"\\]*(?:\\.)?)*"、またはGuy Bedfordが提供するものは、ほとんどのスタックオーバーフローを回避する解析ステップの量を減らします。

8
"(?:\\"|.)*?"

\".を交互に使用すると、エスケープされた引用符が渡されますが、怠zyな量指定子*?は、引用符で囲まれた文字列の終わりを超えないようにします。 .NET Framework REクラスで動作します

8
Tosh Afanasiev
/"(?:[^"\\]++|\\.)*+"/

Perl 5.22.0がインストールされたLinuxシステムでman perlreから直接取得。最適化として、この正規表現は+*の両方の 'posessive'形式を使用してバックトラックを防止します。閉じ引用符のない文字列はいずれの場合も一致しないことが事前にわかっています。

6
ack

これはPCREで完璧に動作し、StackOverflowに該当しません。

"(.*?[^\\])??((\\\\)+)?+"

説明:

  1. 引用符で囲まれた文字列はすべてChar:"で始まります。
  2. 任意の数の文字を含めることができます:.*? {Lazy match};エスケープ文字以外で終わる[^\\];
  3. ステートメント(2)は、ストリングが空( "")になる可能性があるため、Lazy(!)オプションです。だから:(.*?[^\\])??
  4. 最後に、引用符で囲まれた文字列はすべてChar(")で終わりますが、偶数個のエスケープ記号ペア(\\\\)+を前に付けることができます。そして、それはGreedy(!)オプションです:((\\\\)+)?+ {Greedy matching}、bacause文字列は空でも、ペアの終了なしでもかまいません!
4
Vadim Sayfi
/(["\']).*?(?<!\\)(\\\\)*\1/is

引用符で囲まれた文字列で動作するはずです

これは「」と「」の両方で機能するもので、最初に他のユーザーを簡単に追加できます。

( "| ')(?:\\\ 1 | [^\1])*?\ 1

最初のグループ( "または ')にあるものと完全一致する後方参照(\ 1)を使用します。

http://www.regular-expressions.info/backref.html

1
mathias hansen

これまで触れられていないオプションは次のとおりです。

  1. 文字列を逆にします。
  2. 逆の文字列でマッチングを実行します。
  3. 一致した文字列を元に戻します。

これには、エスケープされた開始タグを正しく一致させることができるという追加のボーナスがあります。

次の文字列があるとしましょう。 String \"this "should" NOT match\" and "this \"should\" match"ここで、\"this "should" NOT match\"は一致しないで、"should"は一致する必要があります。その上で、this \"should\" matchは一致し、\"should\"は一致しません。

最初の例。

// 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"']

では、RegExpについて説明しましょう。これは、正規表現を3つの部分に簡単に分割できることです。次のように:

# 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
)

これはおそらく、画像形式でははるかに明確です: Jex's Regulex を使用して生成

github(JavaScript Regular Expression Visualizer)の画像 申し訳ありませんが、画像を含めるほどの評判はありませんので、現時点では単なるリンクです。

この概念を使用したもう少し高度なサンプル関数の要点を次に示します。 https://Gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js

1
scagood

regexpal でめちゃくちゃになり、この正規表現で終わりました:(どのように機能するかを聞かないでください、私はそれを笑って書いたことがほとんどわかりません)

"(([^"\\]?(\\\\)?)|(\\")+)+"
0
Petter Thowsen

一部のファイルの解析を妨げる可能性のある引用文字列を削除しようとすると、同様の問題に直面しました。

私はあなたが思いつくことができる複雑な正規表現を打ち負かす2ステップのソリューションになりました:

 line = line.replace("\\\"","\'"); // Replace escaped quotes with something easier to handle
 line = line.replaceAll("\"([^\"]*)\"","\"x\""); // Simple is beautiful

読みやすく、おそらくより効率的です。

それが最初から検索される場合、これはうまくいくでしょうか?

\"((\\\")|[^\\])*\"
0
user2267983

https://stackoverflow.com/a/10786066/1794894 のより広範なバージョン

/"([^"\\]{50,}(\\.[^"\\]*)*)"|\'[^\'\\]{50,}(\\.[^\'\\]*)*\'|“[^”\\]{50,}(\\.[^“\\]*)*”/   

このバージョンには

  1. 50の最小見積長
  2. 引用符の追加タイプ(開くおよび閉じる
0
Rvanlaak

正規表現はすべての文字列yの特効薬ではないことを覚えておく必要があります。カーソルと線形の手動のシークを使用する方が簡単です。 CFL はかなり簡単にトリックを実行しますが、多くのCFL実装はありません(afaik)。

0
Henrik Paul