捕获组? (?:)做什么?

如何使用?:以及它的优点?


让我试着用一个例子来解释这一点。

考虑以下文字:

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

现在,如果我在下面应用正则表达式...

(https?|ftp)://([^/rn]+)(/[^rn]*)?

...我会得到以下结果:

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

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

但我不关心协议 - 我只想要URL的主机和路径。 所以,我改变了正则表达式来包含非捕获组(?:)

(?:https?|ftp)://([^/rn]+)(/[^rn]*)?

现在,我的结果如下所示:

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

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

看到? 第一组尚未被捕获。 解析器使用它来匹配文本,但稍后会在最终结果中忽略它。


编辑:

按照要求,让我试着解释一下小组。

那么,小组有很多目的。 他们可以帮助您从更大的匹配中提取准确的信息(也可以命名),它们让您重新匹配先前匹配的组,并且可以用于替换。 我们来看一些例子吧?

好吧,假设你有某种XML或HTML(请注意,正则表达式可能不是这项工作的最佳工具,但它作为一个例子很好)。 你想分析标签,所以你可以做这样的事情(我已经添加了空间让它更容易理解):

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

第一个正则表达式有一个命名组(TAG),而第二个正则表达式使用一个公共组。 两个正则表达式都做同样的事情:它们使用第一组中的值(标签的名称)来匹配结束标签。 区别在于第一个使用名称来匹配值,第二个使用组索引(从1开始)。

我们现在尝试一些替代品。 考虑以下文字:

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

现在,让我们使用这个愚蠢的正则表达式:

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

此正则表达式匹配至少包含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

...在它上面,我们试图使用第一组,添加一个下划线,使用第三组,然后第二组,添加另一个下划线,然后是第四组。 结果字符串将如下所示。

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/,它提供了有关正则表达式如何工作的大量细节; 它还提供了一些正则表达式引擎可供选择。


您可以使用捕获组来组织和分析表达式。 非捕获组有第一个好处,但没有第二个开销。 例如,您仍然可以说非捕获组是可选的。

假设你想匹配数字文本,但是一些数字可以写成1st,2nd,3rd,4th,...如果你想捕获数字部分,但不是(可选)后缀,你可以使用非捕获组。

([0-9]+)(?:st|nd|rd|th)?

这将匹配形式1,2,3 ......或第一,第二,第三,...形式的数字,但它只会捕获数字部分。


?:在您想对表达式进行分组时使用,但您不想将其另存为字符串的匹配/捕获部分。

一个例子可能与IP地址相匹配:

/(?:d{1,3}.){3}d{1,3}/

请注意,我不关心保存前3个八位字节,但是(?:...)分组允许我缩短正则表达式,而不会招致捕获和存储匹配的开销。

链接地址: http://www.djcxy.com/p/74769.html

上一篇: capturing group? What does (?:) do?

下一篇: Getting an unresolvable error in JSP