<p>让我举个例子来解释一下。</p>
<p>考虑以下文本:</p>
<pre class="lang-none prettyprint-override"><code>http://stackoverflow.com/
https://stackoverflow.com/questions/tagged/regex
</code></pre>
<p>现在,如果我在上面加上下面的正则表达式。。。</p>
<pre class="lang-regex prettyprint-override"><code>(https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?
</code></pre>
<p>。。。我会得到以下结果:</p>
<pre><code>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"
</code></pre>
<p>但我不关心协议——我只需要URL的主机和路径。因此,我将regex更改为包含非捕获组<code>(?:)</code>。</p>
<pre class="lang-regex prettyprint-override"><code>(?:https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?
</code></pre>
<p>现在,我的结果是这样的:</p>
<pre><code>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"
</code></pre>
<p>看到了吗?第一组还没有被抓获。解析器使用它来匹配文本,但稍后在最终结果中忽略它。</p>
<hr/>
<h2>编辑:</h2>
<p>根据要求,让我也试着解释一下群体。</p>
<p>好吧,团体有很多目的。它们可以帮助您从更大的匹配(也可以命名)中提取准确的信息,它们允许您重新匹配以前匹配的组,并可用于替换。我们来举几个例子,好吗?</p>
<p>好的,假设您有某种XML或HTML(请注意<a href="https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags">regex may not be the best tool for the job</a>,但作为一个例子很好)。您需要解析标记,以便可以执行以下操作(我添加了空格以便于理解):</p>
<pre class="lang-none prettyprint-override"><code> \<(?<TAG>.+?)\> [^<]*? \</\k<TAG>\>
or
\<(.+?)\> [^<]*? \</\1\>
</code></pre>
<p>第一个regex有一个命名组(TAG),而第二个regex使用一个公共组。两个正则表达式都做同样的事情:它们使用第一个组的值(标记的名称)来匹配结束标记。区别在于第一个使用名称来匹配值,第二个使用组索引(从1开始)。</p>
<p>现在让我们试着用一些替代品。考虑以下文本:</p>
<pre class="lang-none prettyprint-override"><code>Lorem ipsum dolor sit amet consectetuer feugiat fames malesuada pretium egestas.
</code></pre>
<p>现在,让我们用这个愚蠢的正则表达式:</p>
<pre class="lang-regex prettyprint-override"><code>\b(\S)(\S)(\S)(\S*)\b
</code></pre>
<p>此正则表达式匹配至少包含3个字符的单词,并使用组分隔前三个字母。结果是:</p>
<pre><code>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"
...
</code></pre>
<p>所以,如果我们应用替换字符串:</p>
<pre class="lang-none prettyprint-override"><code>$1_$3$2_$4
</code></pre>
<p>。。。在上面,我们尝试使用第一个组,添加下划线,使用第三个组,然后是第二个组,添加另一个下划线,然后是第四个组。生成的字符串与下面的字符串类似。</p>
<pre class="lang-none prettyprint-override"><code>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.
</code></pre>
<p>也可以使用命名组进行替换,使用<code>${name}</code>。</p>
<p>为了使用regex,我建议使用<a href="http://regex101.com/" rel="noreferrer">http://regex101.com/</a>,它提供了关于regex如何工作的大量细节;它还提供了一些可供选择的regex引擎。</p>