正则表达式(二)

三、分组引用

3.1、什么是分组

分组指将匹配的内容,使用( )划分成多个组块,分好的组可用于提取、反向引用以及替换操作。

例如在 Java 中

public static void main(String[] args) {
      Pattern pattern=Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
        Matcher matcher = pattern.matcher("小丽生日是2011-11-23");
        if (matcher.find()) {
            String month = matcher.group(2);// 获取第2组中的月份
            System.out.println("月份是:"+month);
        }
    }
// 输出如下结果:
"月份是:11"

3.2、反向引用

在表达式中引用之前的分组,即反向引用

例如

<h1>一级标题</h1>
<h2>二级标题</h2>
<h2>三级标题</h3>
<h4>四级标题</h4>
<h5>五级标题</h5>
<h6>六级标题</h6>
html中共有6级标题,标签是h[1-6],得出匹配正则<h[1-6]>.*?<\/h[1-6]>,正常情况下它能匹配所有标题,问题在于文中的标题三是错误的,<h2>三级标题</h3>,它是h2开头,结尾确是h3

使用反向引用可以更轻松解决这个问题:<(h[1-6])>.*?<\/\1> 步骤拆解如下:

  1. <(h[1-6])> 匹配开始标签,并把标签名加入分组1
  2. .*? 标签中间可以是任意内容。
  3. <\/\1> 匹配结束标签,标签内容通过\1引用分组1(意思是与分组1的内容一致)

正则表达式

反向引用指通过\组号引用之前的分组,可以把分组理解成一个变量,在通过变量名(组号)引用。它不能引用之后的内容,固作称作反向引用,比如这样正则是错误的:<\1>.*?<\/(h[1-6])>

3.3、引用替换

我们经常使正则然后进行替换操作,比如匹配文中所有空行,然后替换成空(删除它),又或者是找出错误的单词,替换成正确的。其实正则有更为强大的替换能力,比如把普通文中所有http链接,一键替换成<a >标签,更厉害一点还可以把文本替换成 insert sql 语句。

请找出下文中所有日期,并统一替换成yyyy-MM-dd格式:

1994-05-27
1972/08/09
1983.05.22
1960/02/19
1986/12/15
1978.01.03
1978/02/21
1964/09/20
1978/08/13
  1. 写出匹配日期的正则:\d{4}[-.\/]\d{2}[-.\/]\d{2}
  2. 对日期年、月、日进行分组:(\d{4})[-.\/](\d{2})[-.\/](\d{2})
  3. 在替换字符中引用分组:$1-$2-$3
替换操作指将正则匹配到的内容,替换成指定字符串,该字符串可通过$组号引用组进行拼装。通过$0可以引用整个匹配的内容。比如:日期“1960/02/19”被匹配之后 $0表示整个日期,$1、$2、$3 分别表示年月日。请注意反向引用与替换引用的语法区别,前者是使用\组号,而替换使用$组号。

注意:$0在 Python与Javascript中不支持,使用$&代替

//Java
String s = "1978/08/13".replaceAll("(\\d{4})[-.\\/](\\d{2})[-.\\/](\\d{2})",
        "$1-$2-$3");
System.out.println(s);
// 输出结果
1978-08-13

大小写转换

在Idea、VS Code、Sublime、Notepad++等工具进行替换操作时,还可以使用下表中操作符进行大小写转换:

操作符 描述
\u 单个转大写 转换一下个字符为大写
\U 全部转大写 转换\U后所有字符转大写
\U…\E 区间转大写 \U与\E区间的内容转大写
\l 单个转小写 转换一下个字符为小写
\L 全部转小写 转换\L后所有字符转小写
\L…\E 区间转小写 \L与\U区间的内容转小写

具体使用方法是:在替换字符串中加入转换操作符。举例把单词首字母转成大写:

  1. 编写匹配正则:\w+
  2. 首字母转大写并替换:\u$0

3.4、分组的其它应用

3.4.1、(?<名称> )命名分组

默认情况下通过组号来取值,此外也可以自定义命名组,语法是(?<名称> ),然后在程序中就可以通过<>中的名称来取值。如:<(?<title>h[1-6])>.*?<\/\1> 该表达式就命名了一个title的组,在js的结果中就可通过title属性取值。

注意:这种命名组只能用于在程序中提取操作,不能进行反向引用,也不能用在替换操作中。上例在替换中如果使用 $title或在反向引用中使用 \title 都是无效的。只能通过组号\1进行引用。这也说明命名组后,组号一样有效。也正因为这种局限性所以命名组使用的很少。

3.4.2、(?: ) 移除分组

()即用于子表达式,同时也是一个分组。如果只想用作子表达式,而不想用于分组就可以使用(?: )从分组列表中移除。比如(?:\d{4})-(\d{2})-(\d{2}) 该表达式只存在两个组,月$1和日$2

3.4.3、( ( ) )嵌套分组

在嵌套分组中组号是如何命名的呢?比如:生日((\d{4})-(\d{2})(\d{2})) 其组号的命名顺序是以开括号出现顺序为准。

正则表达式

3.4.4、()+分组使用量词

同一个分组如果使用了量词,该分组会代表多个值,这时通过$组号去提取值的时候会得到该组最后匹配的值。如(\d)+ 匹配12345,通过$1将得到5

示例
正则为(.+?) / (.+?) / (\d{2}) KG / (\d{4}).(\d{2}).(\d{2})
替换为insert into user (name,city,weight,birthday) values('$1','$2',$3,'$4-$5-$6');

正则表达式

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
247
粉丝
18
喜欢
217
收藏
62
排名:731
访问:9753
私信
所有博文
社区赞助商