web-dev-qa-db-ja.com

正規表現を貪欲でないものにする方法は?

JQueryを使用しています。特殊文字のブロック(開始と終了)を含む文字列があります。その特殊文字ブロックからテキストを取得したいです。文字列内検索に正規表現オブジェクトを使用しました。しかし、2つ以上の特殊文字があるときに複数の結果を見つけるようにjQueryに指示するにはどうすればよいですか?

私のHTML:

<div id="container">
    <div id="textcontainer">
     Cuộc chiến pháp lý giữa [|cơ thử|nghiệm|] thị trường [|test2|đây là test lần 2|] chứng khoán [|Mỹ|day la nuoc my|] và ngân hàng đầu tư quyền lực nhất Phố Wall mới chỉ bắt đầu.
    </div>
</div>

javaScriptコード:

$(document).ready(function() {
  var takedata = $("#textcontainer").text();
  var test = 'abcd adddb';
  var filterdata = takedata.match(/(\[.+\])/);

  alert(filterdata); 

  //end write js 
});

[| c-thử|nghiệm|]thịtrường[| test2 |đâylàtestlần2 |]chứngkhoán[|Mỹ| day la nuoc my |]。しかし、これは私が望む結果ではありません:(。


インターネットで情報を検索した後、作業を​​完了しました^^。次のようなコードを作成します。

var filterdata = takedata.match(/(\[.*?\])/g);
  • 私の結果は:[|cơthử|nghiệm|]、[| test2 |đâylàtestlần2 |]これは正しい!しかし、私はこれを本当に理解していません。私の理由に答えてもらえますか?
203
Rueta

貪欲でない正規表現修飾子は、貪欲なカウンターパートに似ていますが、直後に?が付きます:

*  - zero or more
*? - zero or more (non-greedy)
+  - one or more
+? - one or more (non-greedy)
?  - zero or one
?? - zero or one (non-greedy)
439
Asaph

あなたは貪欲が問題であることは正しいです:

--A--Z--A--Z--
  ^^^^^^^^^^
     A.*Z

A--Zの両方に一致させたい場合は、A.*?Zを使用する必要があります(?*を「気が進まない」、または遅延させます)。

ただし、これを行うためのより良い方法があります。

A[^Z]*+Z

これは、否定文字クラスと所有量限定子を使用して、バックトラッキングを削減し、より効率的です。

あなたの場合、正規表現は次のようになります。

/(\[[^\]]++\])/

残念ながらJavascript regexは所有量指定子をサポートしていないので、あなたはただやらなければならないでしょう:

/(\[[^\]]+\])/

こちらもご覧ください


簡単な要約

*   Zero or more, greedy
*?  Zero or more, reluctant
*+  Zero or more, possessive

+   One or more, greedy
+?  One or more, reluctant
++  One or more, possessive

?   Zero or one, greedy
??  Zero or one, reluctant
?+  Zero or one, possessive

消極的で所有的な量指定子は、有限繰り返し{n,m}構造にも適用できることに注意してください。

Javaの例:

System.out.println("aAoZbAoZc".replaceAll("A.*Z", "!"));  // prints "a!c"
System.out.println("aAoZbAoZc".replaceAll("A.*?Z", "!")); // prints "a!b!c"

System.out.println("xxxxxx".replaceAll("x{3,5}", "Y"));  // prints "Yx"
System.out.println("xxxxxx".replaceAll("x{3,5}?", "Y")); // prints "YY"
35

こんな感じになると思う

takedata.match(/(\[.+\])/g);

末尾のgはグローバルを意味するため、最初の一致で停止しません。

3
iangraham