NoteDeep
什么是分组?什么是后向引用?通过以下示例便可理解。

首先,来说什么是分组。
同样在讲述概念之前,先创建一个名为regextest的文本,其内容如下:
[root@localhost135 ~]# cat regextest
hello
helloo
hellooo
hellohello
abefef
abefefabefef
[root@localhost135 ~]#
首先用之前的连续次数匹配看一个示例:
[root@localhost135 ~]# grep -n "hello\{2\}" regextest
2:helloo
3:hellooo
[root@localhost135 ~]#
上述示例中,表示的是字母 o 连续出现两次即可被匹配,所以第二、第三行都被匹配到了,但如果我们想要从上述文本中找出,2次连续出现hello字符串(也就是找出hellohello),该如何查找呢?
显然 使用"hello\{2\}"并不能实现该查找
这时,我们就需要用到“分组”,将“hello”作为一个分组,当作一个整体,才能达到我们要查找的目的,请看示例:
[root@localhost135 ~]# grep -n "\(hello\)\{2\}" regextest
4:hellohello
[root@localhost135 ~]#
上述示例中,"\(hello\)"表示将hello字符串,当作一个整体,所以"\{2\}"影响的字符就是前面的hello字符串(一个整体)

不难发现,"\( \)"就表示分组,其含义是将其中的内容看作一个分组,看作一个整体去对待

分组也是可以嵌套的,请看如下示例:
[root@localhost135 ~]# grep -n "\(ab\(ef\)\{2\}\)\{2\}" regextest
6:abefefabefef
[root@localhost135 ~]#
可以将上述示例中的表达式分成但三部分理解
第一:最后的 \{2\} ,表示前面的字符连续出现两次
第二:内部的 \(ef\)\{2\} 表示连续出现两次ef,即efef
第三:最外层的 \(ab \) 与内部的efef结合,即abefef,
三者结合在一起,意思就是 连续出现两次 abefef,也就是 abefefabefef
可以看出,最外侧的 "\( \)"又包含另外一个 "\( \)",这就是嵌套

分组 含义相信应该可以理解了,再看看什么是后向引用,同样也是创建一个名为regextest的文本,内容如下:
[root@localhost135 ~]# cat regextest
Hello world Hello
Hiiii world Hiiii
Hello world Hiiii
Hello world Hcccc -- Haaaa
Hiiii world Hello -- Hello
Hello world Hiiii -- Hiiii
abefef
abefefabefef
[root@localhost135 ~]#
之所以先介绍分组,是因为后向引用是以分组为前提的,如果想要实现后向引用,则必须先进行分组。
那到底什么是后向引用呢? 请看如下示例:
[root@localhost135 ~]# grep -n "H.\{4\} world H.\{4\}" regextest
1:Hello world Hello
2:Hiiii world Hiiii
3:Hello world Hiiii
4:Hello world Hcccc -- Haaaa
5:Hiiii world Hello -- Hello
6:Hello world Hiiii -- Hiiii
[root@localhost135 ~]#
上述示例中,"H.\{4\}"表示大写字母H 后面跟随了4个任意字符,所以上述文本中的6行被匹配到
那如果我们想要从上述文本中找出,world 前后单词相同的那些行,换句话说,就是world之前是hello,world之后也要是hello,此时我们应该怎么做呢?

这时,就需要用到“后向引用”,请看示例:
[root@localhost135 ~]# grep -n "\(H.\{4\}\) world \1" regextest
1:Hello world Hello
2:Hiiii world Hiiii
[root@localhost135 ~]#
通过上述示例的正则表达式,实现了我们的目的,表达式具体是什么意思呢?我们可以分解来看
第一: "\(H.\{4\}\)"
第二: "\1"
第一部分不难理解,与之前示例的正则只有一点点区别,就是在原来的基础上添加了分组,将"H.\{4\}"变成了 "\(H.\{4\}\)",表示的含义就是把字母H后面跟随的4个任意字符看作一个整体。
第二部分 "\1"表示整个正则中第一个分组中的正则所匹配到的结果。
白话文讲一遍:在上述示例中,整个正则只出现了一个分组,就是"\(H.\{4\}\)",当它与示例文件中的第一行文本进行匹配时,会匹配到Hello字符串,这时 "\1"就是表示Hello字符串,当它与示例文件中的第二行匹配时,会匹配到Hiiii,这是 "\1"就表示Hiiii字符串。
换句话说,"\1"引用了整个正则中第1个分组中的正则所匹配到的结果。
这就是所谓的“后向引用”。

"\1"表示引用整个正则中第1个分组的正则所匹配到的结果
"\2"表示引用整个正则中第2个分组的正则所匹配到的结果
请看示例:
[root@localhost135 ~]# grep -n "\(H.\{4\}\) world \(H.\{4\}\) -- \2" regextest
5:Hiiii world Hello -- Hello
6:Hello world Hiiii -- Hiiii
[root@localhost135 ~]#

不过,当分组嵌套时,如何区分整个正则中,哪个是第一个分组,哪个是第二个分组呢?请看下图,具体示例就不演示了。
分组的顺序取决于分组符号的左侧部分的顺序
上图中红线部分是第一个分组,蓝线部分是第二个分组
注意:排序时也仅仅按照分组符号的左侧部分排序,分组符号的右侧部分不算在排序范围内

总结:
  1. "\( \)" 表示分组,将其中的内容看作一个整体,分组可以嵌套
  2. "\1"表示引用整个正则中第1个分组的正则所匹配到的结果
  3. "\2"表示引用整个正则中第2个分组的正则所匹配到的结果



评论列表