web-dev-qa-db-ja.com

正規表現の疑問符

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

ありがとうございました

36
xralf

???の主な違いは、lazinessに関係します。 ??はレイジーですが、?はレイジーではありません。

テキストの本文で「車」という単語を検索したいが、単数の「車」だけに制限されたくないとしましょう。また、複数の「車」と照合する必要があります。

以下に例を示します。

I own three cars.

ここで、「car」という単語に一致させたい場合および戻り値として「car」という文字列のみを取得したい場合、次のように遅延??を使用します。

cars??

これは、「Wordの車を探します。どちらかを見つけたら、carを返し、それ以上は返しません」と言います。

ここで、同じ単語(「car」または「cars」)と一致させたい場合および一致するものすべてを返したいの場合、以下のように非遅延?を使用します。

cars?

これは、「Wordの車を探して、車または車のいずれかを返します」と言います。

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

個人的には、他の正規表現演算子(?*演算子など)をレイジーにする方法として+を使用しているのは、単純な文字のオプションに使用するよりも頻繁ですが、YMMVです。

コードで見る

以下は、例としてClojureで実装された上記の例です。

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

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

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

34
semperos

これは素晴らしい質問であり、怠な??量指定子のポイントを自分で確認するにはしばらく時間がかかりました。

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

?の有用性は理解するのに十分簡単です。 httphttpsの両方を検索する場合は、次のようなパターンを使用できます。

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

最初に思い浮かぶのは、 this

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

それらはすべて合格しますが、グループ2で456のみが必要だったため、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番目の入力は間違ってグループ化されます(+も同じですが、?が最初に来ました)。 shttps?の一部であるか[a-z]+|\d+の一部であるかを決定するとき、結果がいずれかのパスである場合、正規表現エンジンは常に左側のものを選択します。したがって、グループ2はsを失います。これは、グループ1が吸い込んだためです。

これを修正するには、 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に入れることを好みます。

31
Justin Morgan

?は、単に前のアイテム(キャラクター、キャラクタークラス、グループ)をオプションにします:

colou?r

「色」と「色」に一致

(swimming )?pool

「プール」と「プール」に一致

??は同じですが、怠laでもあるため、可能な場合はwillを除外します。それらのドキュメントが述べているように、??実際にはまれです。私はそれを使ったことがない。

11

正規表現での疑問符のその他の使用

他の回答で説明されていることとは別に、正規表現で疑問符を使用する方法はまだ3つあります。

  1. 負の先読み

    負の先読みは、他の何かが後に続かないものと一致させたい場合に使用されます。負の先読み構造は括弧のペアであり、開始括弧の後に疑問符と感嘆符が続きます。 x(?!x2)

    example

    • 単語Thereを考えます
    • 現在、デフォルトでは、RegEx eは、Word eの3番目の文字Thereを見つけます。

      _There
        ^
      _
    • ただし、すぐにeが続くrが必要ない場合は、RegEx e(?!r)を使用できます。結果は次のようになります。

      _There
          ^
      _
  2. 正の先読み

    ポジティブルックアヘッドは同じように機能します。 q(?=u)は、qを一致の一部にせずに、直後にuが続くuと一致します。ポジティブルックアヘッドコンストラクトは、括弧のペアであり、開き括弧の後に疑問符と等号が続きます。

    example

    • 単語gettingを考えます
    • 現在、デフォルトでは、RegEx tは、Word tの3番目の文字gettingを見つけます。

      _getting
        ^
      _
    • ただし、すぐにtが続くiが必要な場合は、RegEx t(?=i)を使用できます。結果は次のようになります。

      _getting
         ^
      _
  3. 非キャプチャグループ

    括弧_()_に正規表現を配置すると、番号付きのキャプチャグループが作成されます。括弧内の正規表現の部分と一致する文字列の部分を保存します。

    グループで一致をキャプチャする必要がない場合は、この正規表現を最適化して

    _(?:Value)
    _

this および this も参照してください。

8
Raman Sahasi