67

正規表現のリファレンスを読んでいて、次のことを考えています。と ??文字。それらの有用性をいくつかの例で説明していただけますか? 私はそれらを十分に理解していません。

ありがとうございました

4

5 に答える 5

65

これは素晴らしい質問であり、私??自身が遅延量指定子の要点を理解するのにしばらく時間がかかりました。

? - オプションの (貪欲な) 量指定子

の有用性?は簡単に理解できます。httpと の両方を見つけたい場合はhttps、次のようなパターンを使用できます。

https?

このパターンは、sオプションになるため、両方の入力に一致します。

?? - オプションの (遅延) 量指定子

??はより微妙です。通常は同じことを?行います。「この入力はこの正規表現を満たしていますか?」と尋ねても、真/偽の結果は変わりません。代わりに、「この入力のどの部分がこの正規表現に一致し、どの部分がどのグループに属しているか?」という質問に関連しています。入力が複数の方法でパターンを満たすことができる場合、エンジンは?vs. ??(または*vs. *?、または+vs. +?) に基づいてグループ化する方法を決定します。

検証して解析したい一連の入力があるとします。これは(確かにばかげた)例です:

Input:       
http123
https456
httpsomething

Expected result:
Pass/Fail  Group 1   Group 2
Pass       http      123
Pass       https     456
Pass       http      something

最初に頭に浮かぶことを試してみてください。これはのとおりです。

^(http)([a-z\d]+)$
Pass/Fail  Group 1   Group 2    Grouped correctly?
Pass       http      123        Yes
Pass       http      s456       No
Pass       http      something  Yes

それらはすべてパスしますが456、グループ 2 のみが必要なため、2 番目の結果セットは使用できません。

よし、やり直そ。グループ 2 は文字または数字にすることができますが、両方にすることはできません。

(https?)([a-z]+|\d+)
Pass/Fail  Group 1   Group 2   Grouped correctly?
Pass       http      123       Yes
Pass       https     456       Yes
Pass       https     omething  No

?これで 2 番目の入力は問題ありませんが、3 番目の入力はデフォルトで貪欲であるため、間違ってグループ化されています (これ+もそうですが、?最初に来ました)。がまたはのs一部であるかどうかを判断するとき、結果がいずれかのパスである場合、正規表現エンジンは常に左側のものを選択します。したがって、グループ 1 がそれ​​を吸ったので、グループ 2 が負けます。https?[a-z]+|\d+s

これを修正するには、1 つの小さな変更を加えます。

(https??)([a-z]+|\d+)$
Pass/Fail  Group 1   Group 2    Grouped correctly?
Pass       http      123        Yes
Pass       https     456        Yes
Pass       http      something  Yes

基本的に、これは次のことを意味します。「必要に応じて一致httpsしますが、グループ 1 がhttp. sエンジンは、 が の一部として機能する可能性があることを認識する[a-z]+|\d+ため、それをグループ 2 に配置することを優先します。

于 2011-04-07T15:49:38.267 に答える
53

との主な違いは???その怠惰性に関するものです。??怠け者で?はありません。

たとえば、テキスト本文で "car" という単語を検索したいが、単数形の "car" だけに限定したくないとします。また、複数形の「車」に対しても一致させたいと考えています。

これが例文です:

I own three cars.

ここで、"car" という単語に一致させたい場合、文字列 "car" のみを取得し??たい場合は、次のように遅延を使用します。

cars??

これは、「単語 car または cars を探してください。どちらかが見つかった場合は、戻るcarだけでそれ以上は何もありません」という意味です。

ここで、同じ単語 (「car」または「cars」)と一致させたい場合、一致全体を返したい場合は、次の?ように非遅延を使用します。

cars?

これは、「単語 car または cars を探し、見つけたものは何でも car または cars のいずれかを返す」ことを示しています。

コンピュータ プログラミングの世界では、レイジーとは一般に「必要なだけ評価する」ことを意味します。そのため、レイジー??は一致を作成するために必要な量だけを返します。「cars」の「s」はオプションであるため、返さないでください。反対に、非遅延 (欲張りと呼ばれることもあります) 操作は可能な限り評価するため?、オプションの "s" を含むすべての一致が返されます。

個人的に?は、他の正規表現演算子 ( *and+演算子など) を単純な文字のオプション性よりも頻繁に使用する方法として、YMMV を使用していることに気付きました。

コードで見る

例として Clojure で実装された上記を次に示します。

(re-find #"cars??" "I own three cars.")
;=> "car"

(re-find #"cars?" "I own three cars.")
;=> "cars"

itemre-findは、最初の引数を正規表現として受け取り#"cars??"、2 番目の引数で見つかった最初の一致を返す関数です。"I own three cars."

于 2011-04-07T15:49:52.887 に答える
15

?前の項目 (文字、文字クラス、グループ) をオプションにするだけです。

colou?r

「色」と「色」に一致

(swimming )?pool

「プール」と「プール」にマッチ

??は同じですが、怠け者でもあるため、可能であればそのアイテム除外されます。それらのドキュメントが指摘するように、?? 実際にはまれです。私はそれを使用したことがありません。

于 2011-04-07T15:28:14.637 に答える