7

'のいずれかに一致"し、次に他の文字に一致する正規表現を作成します。最初に遭遇した内容に応じて、 a'またはそれぞれが一致したときに終了します。"したがって、この問題は、最後に後方参照を使用することで解決できるほど単純に見えます。以下にいくつかの正規表現コードを示します(Javaであるため、\beforeなどの余分なエスケープ文字に注意して"ください)。

private static String seekerTwo = "(['\"])([a-zA-Z])([a-zA-Z0-9():;/`\\=\\.\\,\\- ]+)(\\1)";

このコードは、次のようなものを正常に処理します。

"hello my name is bob"
'i live in bethnal green'

次のような文字列があると問題が発生します。

"hello this seat 'may be taken' already"

上記の正規表現を使用すると、最初の部分で遭遇すると失敗し、'続行して正常に一致し'may be taken'ます...しかし、これは明らかに不十分です。文字列全体を一致させる必要があります。

私が考えているのは、最初のグループで一致しなかった引用符のタイプを、3番目のグループの文字セットに文字として含めることによって無視する方法が必要だということです。しかし、私はこれを行う方法を知りません。ある種の卑劣なNOT後方参照関数か何かがありますか?一致しなかった最初のグループのキャラクターを参照するために使用できるものはありますか?それとも、私の苦境に対するある種の解決策ですか?

4

2 に答える 2

12

これは、否定先読みアサーションを使用して実行できます。次の解決策では、文字列内の引用符をエスケープできることも考慮に入れています。

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

説明:

(["'])    # Match and remember a quote.
(?:       # Either match...
 \\.      # an escaped character
|         # or
 (?!\1)   # (unless that character is identical to the quote character in \1)
 .        # any character
)*        # any number of times.
\1        # Match the corresponding quote.

"hello this seat 'may be taken' already"これはまたはに正しく一致し"hello this seat \"may be taken\" already"ます。

Java では、すべてのバックスラッシュを使用して:

Pattern regex = Pattern.compile(
    "([\"'])   # Match and remember a quote.\n" +
    "(?:       # Either match...\n" +
    " \\\\.    # an escaped character\n" +
    "|         # or\n" +
    " (?!\\1)  # (unless that character is identical to the matched quote char)\n" +
    " .        # any character\n" +
    ")*        # any number of times.\n" +
    "\\1       # Match the corresponding quote", 
    Pattern.COMMENTS);
于 2012-03-15T11:05:44.543 に答える
2

ルックアラウンド(Javaがサポートしている)を使用できる場合、Timのソリューションはかなりうまく機能します。ただし、ルックアラウンドをサポートしていない言語またはツールを使用していることに気付いた場合は、両方のケース(二重引用符で囲まれた文字列と一重引用符で囲まれた文字列)を別々に一致させることができます。

"(\\"|[^"])*"|'(\\'|[^'])*'

各ケースに個別に一致しますが、どちらかのケースを全体の一致として返します


でも

どちらの場合も、少なくとも1つの不測の事態の犠牲になる可能性があります。よく見ていない場合は、この抜粋に2つの一致があるはずだと思うかもしれません。

彼は自転車に乗るようになりました。「これがすべて終わったら、後で会いましょう」と彼は旅を始める前に少し振り返って言った。彼が通りに入ると、街のトロリーの1つがマイクの自転車に衝突しました。「オーマイ!」見物人は叫んだ。

...しかし、2つではなく3つの一致があります:

"I'll see you later, when I'm done with all this"
's trolleys collided with Mike'
"Oh my!"

この抜粋には、一致するものが1つだけ含まれています。

しかし、戦いはまだ終わっていませんでした。"おい!" ボブは叫んだ。"なんでしょう?" 私はレトルトしました。「私はあなたの内臓が嫌いです!」「どうして気にするの?」"なぜなら私はあなたを愛しているから!" "あなたがやる?" ボブは、「いいえ、私はあなたを愛することができませんでした!」とささやく前に少し立ち止まりました。

あなたはそれを見つけることができますか?:D

't over yet, though. "Hey!" yelled Bob. "What do you want?" I retorted. "I hate your guts!" "Why would I care?" "Because I love you!" "You do?" Bob paused for a moment before whispering "No, I couldn'

(ルックアラウンドを使用する場合)、追加のチェック(最初の引用の前に空白などのポジティブルックビハインドなど)を実行して、次のようなものと一致しないことを確認することをお勧めします's trolleys collided with Mike'-私はしませんが最初に多くのテストを行わずに、ソリューションに多額の資金を投入します。いずれかの式の先頭に追加(?<=\s|^)すると、上記のケースを回避できます...つまり:

(?<=\s|^)(["'])(?:\\.|(?!\1).)*\1                    #based on Tim's

また

(?<=\s|^)("(\\"|[^"])*"|'(\\'|[^'])*')               #based on my alternative

ルックアラウンドが非ルックアラウンドと比較してどれほど効率的かわからないので、上記の2つは同等であるか、一方が他方よりも効率的である可能性があります(?)

于 2012-03-15T13:32:15.793 に答える