正则表达式相关

张天宇 on 2020-05-22

正则表达式一些入门知识,还有在牛客遇到的题目。

正则表达式是一个强大的字符串处理工具,可以对字符串进行查找、提取、分割、替换等操作。

作用

  • 测试字符串内的模式。
    例如,可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式。这称为数据验证。
  • 替换文本。
    可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。
  • 基于模式匹配从字符串中提取子字符串。
    可以查找文档内或输入域内特定的文本。

语法

匹配单个字符

. 可以用来匹配任何的单个字符,但是在绝大多数实现里面,不能匹配换行符;如果需要匹配 . ,那么要用 \ 进行转义,即在 . 前面加上 \ 。

1
z.y # 匹配结果 zty

匹配一组字符

[ ] 定义一个字符集合;0-9、a-z 定义了一个字符区间,区间使用 ASCII 码来确定,字符区间在 [ ] 中使用。

- 只有在 [ ] 之间才是元字符,在 [ ] 之外就是一个普通字符;

^ 在 [ ] 中是取非操作。

1
abc[^0-9] # 匹配以abc为开头,并且最后一个字母不为数字的字符串

使用元字符

匹配特定字符
  1. 数字元字符

    元字符 说明
    \d 数字字符,等价于 [0-9]
    \D 非数字字符,等价于 [^0-9]
  2. 字母数字元字符

    元字符 说明
    \w 大小写字母,下划线和数字,等价于 [a-zA-Z0-9_]
    \W 对 \w 取非
  3. 空白字符元字符

    元字符 说明
    \s 任何一个空白字符,等价于 [\f\n\r\t\v]
    \S 对 \s 取非

    \x 匹配十六进制字符,\0 匹配八进制,例如 \xA 对应值为 10 的 ASCII 字符 ,即 \n。

重复匹配

  • + 匹配 1 个或者多个字符
  • \ * 匹配 0 个或者多个字符
  • ? 匹配 0 个或者 1 个字符
1
[\w.]+@\w+\.\w+ # 匹配邮箱地址 [\w.] 匹配的是字母数字或者 . ,在其后面加上 + ,表示匹配多次。在字符集合 [ ] 里,. 不是元字符;

位置匹配

单词匹配

\b 可以匹配一个单词的边界,边界是指位于 \w 和 \W 之间的位置;\B 匹配一个不是单词边界的位置。

\b 只匹配位置,不匹配字符,因此 \babc\b 匹配出来的结果为 3 个字符。

字符串边界

^ 匹配整个字符串的开头,$ 匹配结尾。

^ 元字符在字符集合中用作求非,在字符集合外用作匹配字符串的开头。

分行匹配模式(multiline)下,换行被当做字符串的边界。

1
^\s*\/\/.*$ # 匹配代码中以 // 开始的注释行

使用子表达式

使用 ( ) 定义一个子表达式。子表达式的内容可以当成一个独立元素,即可以将它看成一个字符,并且使用 * 等元字符。

1
(ab){2,} # abababab

| 是或元字符,它把左边和右边所有的部分都看成单独的两个部分,两个部分只要有一个匹配就行。

1
(19|20)\d{2} # 1900 2010
1
2
3
4
5
6
7
((25[0-5]|(2[0-4]\d)|(1\d{2})|([1-9]\d)|(\d))\.){3}(25[0-5]|(2[0-4]\d)|(1\d{2})|([1-9]\d)|(\d))
# 匹配IP地址
# 一位数字
# 不以 0 开头的两位数字
# 1 开头的三位数
# 2 开头,第 2 位是 0-4 的三位数
# 25 开头,第 3 位是 0-5 的三位数

回溯引用

回溯引用使用 \n 来引用某个子表达式,其中 n 代表的是子表达式的序号,从 1 开始。它和子表达式匹配的内容一致,比如子表达式匹配到 abc,那么回溯引用部分也需要匹配 abc 。

1
<(h[1-6])>\w*?<\/\1> # 匹配html前后标签一致的合法标签,如<h1>dsdad</h1>
替换
1
2
3
(\d{3})(-)(\d{3})(-)(\d{4})
($1) $3-$5
# 313-555-1234 替换为 (313)555-1234
大小写转换
元字符 说明
\l 把下个字符转换为小写
\u 把下个字符转换为大写
\L 把\L 和\E 之间的字符全部转换为小写
\U 把\U 和\E 之间的字符全部转换为大写
\E 结束\L 或者\U
1
2
3
4
(\w)(\w{2})(\w)
$1\U$2\E$3
# 把文本第二三个字符转成大写
# abcd 转 aBCd

相关题目[牛客]

身份证匹配

1
2
3
4
5
6
7
8
9
10
# 15位身份证的构成:六位出生地区码+六位出身日期码+三位顺序码
# 18位身份证的构成:六位出生地区码+八位出生日期码+三位顺序码+一位校验码
isIDCard=/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/;
# [1-9]\d{7}:六位出生地区码+两位出生日期码的年份,这里的年份指后两位,因此没有第一位不能为0的限制,所以合并了。
isIDCard=/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$/;
# [1-9]\d{5}:六位出生地区码,出生地区码没有以0开头,因此第一位为[1-9]。
# [1-9]\d{3}:八位出生日期码的四位年份,同样年份没有以0开头。
# ((0\d)|(1[0-2])):八位出生日期码的两位月份,| 表示或者,月份的形式为0\d或者是10、11、12。
# (([0|1|2]\d)|3[0-1]):八位出生日期码的两位日期,日期由0131
# \d{4}:三位顺序码+一位校验码,共四位。

Bilibili网址匹配

1
2
3
4
5
6
7
# http://www.bilibili.com/video/av21061574
/^(http:\/\/)?(\w+)\.bilibili\.com\/?video\/av(\d{1,8})\/?$/
# ^表示匹配输入的开始,$表示匹配输入的结束
# ?表示匹配某元素0次或1次,这里四个选项都没有问题,能够匹配0次或1次字符http后面的s
# \w 表示匹配字母数字或下划线
# +表示匹配某元素1次或多次
# \d匹配数字,{m,n}表示最少匹配m次,最多匹配n次,\/?能匹配末尾的0个或1个/字符

参考链接

CS-Notes/正则表达式