非捕获组,即(?:)
,是如何在正则表达式中使用的?它们有什么好处
让我试着用一个例子来解释这一点
考虑以下案文:
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(请注意,正则表达式可能不是执行此任务的最佳工具,但作为一个示例,它很好)。您希望解析标记,因此可以执行类似的操作(我添加了空格以便于理解):
\<;(?<;标记>;+)\>;[^<;]*\</\k<;标签>\&燃气轮机;
或
\<;(.+?)\>;[^<;]*\</\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/,提供了有关正则表达式如何工作的大量详细信息;它还提供了一些可供选择的正则表达式引擎