什么是正则表达式中的非捕获组?

非捕获组,即(?:),是如何在正则表达式中使用的?它们有什么好处

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

考虑以下案文:

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

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

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

。。。我将得到以下结果:

匹配”http://stackoverflow.com/"
第1组:“http”
第二组:“stackoverflow.com”
第3组:“/”
匹配“https://stackoverflow.com/questions/tagged/regex"
第1组:“https”
第二组:“stackoverflow.com”
第3组:“/questions/taged/regex”

但我不关心协议——我只需要URL的主机和路径。因此,我将正则表达式更改为包含非捕获组(?:)

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

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

匹配”http://stackoverflow.com/"
第一组:“stackoverflow.com”
第2组:“/”
匹配“https://stackoverflow.com/questions/tagged/regex"
第一组:“stackoverflow.com”
第2组:“/questions/taged/regex”

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


编辑:

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

嗯,团体有很多目的。它们可以帮助您从更大的匹配(也可以命名)中提取准确信息,让您重新匹配先前匹配的组,并可用于替换。我们来举几个例子,好吗

假设您有某种XML或HTML(请注意,正则表达式可能不是执行此任务的最佳工具,但作为一个示例,它很好)。您希望解析标记,因此可以执行类似的操作(我添加了空格以便于理解):

\<(?<标记>+)\>[^<]*\&lt/\k<标签&gt\&燃气轮机;
或
\<(.+?)\>[^<]*\&lt/\1\>

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

现在让我们尝试一些替换。考虑下面的文本:

Lorem ipsum door sit amet concertetuer feugiat fames malesuada pretium egestas。

现在,让我们在上面使用这个哑正则表达式:

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

此正则表达式匹配至少3个字符的单词,并使用组分隔前三个字母。结果是:

匹配“Lorem”
第1组:“L”
第2组:“o”
第3组:“r”
第4组:“新兴市场”
匹配“同侧”
第一组:“我”
第2组:“p”
第3组:“s”
第四组:“嗯”
...
匹配“Concertetuer”
第一组:“c”
第2组:“o”
第3组:“n”
第4组:“部门用户”
...

因此,如果我们应用替换字符串:

$1\u3$2\u4

。。。在它上面,我们尝试使用第一组,添加一个下划线,使用第三组,然后是第二组,再添加一个下划线,然后是第四组。生成的字符串与下面的字符串类似

L_ro_em i_um d_lou_或s_ti_em t c_no_sectuetuer f_u u giat f_la_esuada p_tiu e e_stas。

您也可以使用命名组进行替换,使用${name}

要玩regex,我建议http://regex101.com/,提供了有关正则表达式如何工作的大量详细信息;它还提供了一些可供选择的正则表达式引擎

发表评论