1. ホーム
  2. regex

[解決済み] 正規表現における非捕捉グループとは何ですか?

2022-03-18 16:01:04

質問

非捕獲グループ、すなわち、どのように。 (?:) 正規表現ではどのように使われ、どのような用途に使われるのですか?

どのように解決するのですか?

例を挙げて説明しましょう。

次のような文章を考えてみましょう。

http://stackoverflow.com/
https://stackoverflow.com/questions/tagged/regex

ここで、以下の正規表現を適用すると...

(https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?

... 次のような結果になりますね。

Match "http://stackoverflow.com/"
     Group 1: "http"
     Group 2: "stackoverflow.com"
     Group 3: "/"

Match "https://stackoverflow.com/questions/tagged/regex"
     Group 1: "https"
     Group 2: "stackoverflow.com"
     Group 3: "/questions/tagged/regex"

しかし、私はプロトコルは気にしません -- URLのホストとパスが欲しいだけなのです。そこで、正規表現を変更して、キャプチャしないグループを含めるようにします。 (?:) .

(?:https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?

さて、私の結果は次のようになります。

Match "http://stackoverflow.com/"
     Group 1: "stackoverflow.com"
     Group 2: "/"

Match "https://stackoverflow.com/questions/tagged/regex"
     Group 1: "stackoverflow.com"
     Group 2: "/questions/tagged/regex"

ほらね。最初のグループは捕捉されていないのです。パーサーはそれを使ってテキストをマッチングしますが、最終結果では後でそれを無視します。


EDITです。

リクエストにお応えして、グループについても説明してみます。

さて、グループには多くの目的があります。大きなマッチから正確な情報を抽出したり(名前をつけることもできます)、前にマッチしたグループと再マッチさせたり、置換に使ったりします。いくつか例を挙げてみましょう。

ある種のXMLやHTMLがあるとします。 正規表現が最適なツールであるとは限りません。 しかし、例としてはいい感じです)。タグを解析したいので、次のようにします(わかりやすくするためにスペースを入れています)。

   \<(?<TAG>.+?)\> [^<]*? \</\k<TAG>\>
or
   \<(.+?)\> [^<]*? \</\1\>

最初の正規表現では名前付きグループ(TAG)を使用し、2番目の正規表現では共通グループを使用しています。どちらの正規表現も、最初のグループの値(タグの名前)を使って閉じタグをマッチさせるという点では同じです。違いは、最初のものは値をマッチさせるために名前を使用し、2番目のものはグループのインデックス(1から始まる)を使用する点です。

では、いくつかの置換を試してみましょう。次のようなテキストを考えてみましょう。

Lorem ipsum dolor sit amet consectetuer feugiat fames malesuada pretium egestas.

さて、その上でこの馬鹿な正規表現を使ってみよう。

\b(\S)(\S)(\S)(\S*)\b

この正規表現は、少なくとも3文字の単語にマッチし、最初の3文字を区切るためにグループを使用します。結果はこのようになります。

Match "Lorem"
     Group 1: "L"
     Group 2: "o"
     Group 3: "r"
     Group 4: "em"
Match "ipsum"
     Group 1: "i"
     Group 2: "p"
     Group 3: "s"
     Group 4: "um"
...

Match "consectetuer"
     Group 1: "c"
     Group 2: "o"
     Group 3: "n"
     Group 4: "sectetuer"
...

そこで、置換文字列を適用すると

$1_$3$2_$4

...その上で、最初のグループを使い、アンダースコアを加え、3番目のグループを使い、次に2番目のグループを使い、さらにアンダースコアを加え、4番目のグループを使おうとしているのです。その結果、以下のような文字列になる。

L_ro_em i_sp_um d_lo_or s_ti_ a_em_t c_no_sectetuer f_ue_giat f_ma_es m_la_esuada p_er_tium e_eg_stas.

名前付きグループを置換に使用することもできます。 ${name} .

正規表現で遊ぶには、以下の方法がお勧めです。 http://regex101.com/ には、正規表現がどのように機能するのかについての十分な詳細が記載されており、また、いくつかの正規表現エンジンから選択することができます。