正则表达式


正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个”规则字符串”, 这个”规则字符串”用来表达对字符串的一种过滤逻辑.

规定一些特殊语法表示字符类、数量限定符和位置关系,然后用这些特殊语法和普通字符一起表示一个模式,这就是正则表达式(Regular Expression).

给定一个正则表达式和另一个字符串,我们可以达到如下的目的:

  • 1.给定的字符串是否符合正则表达式的过滤逻辑(称作”匹配”)
  • 2.可以通过正则表达式,从字符串中获取我们想要的特定部分.

正则表达式的特点

  • 1.灵活性、逻辑性和功能性非常的强
  • 2.可以迅速地用极简单的方式达到字符串的复杂控制

正则表达式组成

  • 1.字符类
  • 2.数量限定符
  • 3.位置限定符

字符类

. 匹配单个字符

1.可以用来匹配任何的单个字符,但是在绝大多数实现里面,不能匹配换行符;

2.它有特殊的含义,而不是字符本身的含义.如果需要匹配.,那么要用\进行转义,即\.

# abc. 可以匹配`abcd`,'abc9'
echo "abc9
aassds
abcdefg" | grep --color 'abc.'

[ ] 匹配一组字符

1.0-9、a-z 定义了一个字符区间,区间使用ASCII码来确定,字符区间在[ ]中使用.

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

3.^ 在[ ]中是取非操作.

# [abc]d 可以匹配`ad`,`bd`,`cd`
txt="ads-dcd-ssxd-adss-1ds-ds-4ds-dsd"
echo $txt | grep --color '[abc]d'
echo $txt | grep --color '[a-z0-9]d'
echo $txt | grep --color '[^a-d^-]d'

数量限定符

数量限定符(Quantifier): 邮件地址的每一部分可以有一个或多个x字符,IP地址的每一部 分可以有1-3个y字符

1.+ 匹配1个或者多个字符

2.* 匹配0个或者多个字符

3.? 匹配0个或者1个字符

4.{n}匹配n个字符

5.{m,n}匹配m~n个字符

6.{m,}至少匹配m个字符

7.*+都是贪婪型元字符,会匹配尽可能多的内容.在后面加?可以转换为懒惰型元字符,例如*?+?{m,n}?

txt="helllloooooooo world"
echo $txt | grep -E --color 'hel+'
echo $txt | grep -E --color 'hel*'
echo $txt | grep -E --color 'hel?'
echo $txt | grep -E --color 'hel{3}'
echo $txt | grep -E --color 'hel{3,5}'
echo $txt | grep -E --color 'hellllo{3,}'

位置限定符

字符串边界

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

2.$匹配整个字符串的结尾

单词边界

1.\b可以匹配一个单词的边界,边界是指位于\w\W之间的位置;\b只匹配位置,不匹配字符,因此\babc\b匹配出来的结果为3个字符

2.\B匹配一个不是单词边界的位置

3.\<匹配单词开头的位置

4.\>匹配单词结尾的位置

txt="look at atis thisat book."
echo $txt | grep -E --color '^look'
echo $txt | grep -E --color 'ok.$'
echo $txt | grep -E --color '\bat\b'
echo $txt | grep -E --color '\bat'
echo $txt | grep -E --color 'at\b'
echo $txt | grep -E --color '\Bat'
echo $txt | grep -E --color 'at\B'
echo $txt | grep -E --color '\<at\>'
echo $txt | grep -E --color '\<at'
echo $txt | grep -E --color 'at\>'

特殊元字符

# 匹配空白字符
[\b]  回退(删除)一个字符
\f  换页符
\n  换行符
\r  回车符
\t  制表符
\v  垂直制表符
## \r\n 是`Windows`中的文本行结束标签,在`Unix/Linux`则是`\n`
## \r\n\r\n 可以匹配`Windows`下的空白行,因为它匹配两个连续的行尾标签,而这正是两条记录之间的空白行

# 数字元字符
\d  数字字符,等价于 [0-9]
\D  非数字字符,等价于 [^0-9]

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

# 空白字符元字符
\s  任何一个空白字符,等价于 [\f\n\r\t\v]
\S  对 \s 取非
## \x 匹配十六进制字符,\0 匹配八进制,例如 \xA 对应值为`10`的`ASCII`字符,即`\n`

使用子表达式

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

2.子表达式可以嵌套,但是嵌套层次过深会变得很难理解.

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

# 应用: 匹配`IP`地址
# # IP 地址中每部分都是 0-255 的数字,用正则表达式匹配时以下情况是合法的

#   一位数字
#   不以 0 开头的两位数字
#   1 开头的三位数
#   2 开头,第 2 位是 0-4 的三位数
#   25 开头,第 3 位是 0-5 的三位数
echo IP: 10.1.100.99 XXX | grep -E --color '((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))'

\n回溯引用

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

# 应用: 匹配 HTML 中合法的标题元素
# \1 将回溯引用子表达式 (h[1-6]) 匹配的内容,也就是说必须和子表达式匹配的内容一致
echo "<h1>test</h1>" | grep -E --color "<(h[1-6])>\w*?<\/\1>"

替换

# 应用: 修改电话号码格式
# 文本: 139-1555-1234
# 在第一个子表达式查找的结果加上`()`,然后加一个空格,在第三个和第五个字表达式查找的结果中间加上`-`进行分隔
echo "139-1555-1234" | grep -E --color "(\d{3})(-)(\d{4})(-)(\d{4}) (\1) \3-\5"
# 结果: (139) 1555-1234

大小写转换

# 应用: 把文本的第二个和第三个字符转换为大写
# 文本: abcd
# 1.查找
(\w)(\w{2})(\w)
# 2.替换
$1\U$2\E$3
# 结果: aBCd

# 说明
#   \l  把下个字符转换为小写
#   \u  把下个字符转换为大写
#   \L  把\L 和\E 之间的字符全部转换为小写
#   \U  把\U 和\E 之间的字符全部转换为大写
#   \E  结束\L 或者\U

前后查找

前后查找规定了匹配的内容首尾应该匹配的内容,但是又不包含首尾匹配的内容.

1.向前查找使用?=定义,它规定了尾部匹配的内容,这个匹配的内容在?= 之后定义.所谓向前查找,就是规定了一个匹配的内容,然后以这个内容为尾部向前面查找需要匹配的内容.

2.向后匹配用?<=定义

注: JavaScript 不支持向后匹配,Java 对其支持也不完善

# 应用: 查找出邮件地址`@`字符前面的部分
# 文本: test@qq.com
\w+(?=@)

嵌入条件

回溯引用条件

条件为某个子表达式是否匹配,如果匹配则需要继续匹配条件表达式后面的内容

# 应用: 匹配字符串被小括号包含或未包含
# 文本1: (test)
# 文本2: test
# 子表达式`(\()`匹配一个左括号,其后的`?`表示匹配`0`个或者`1`个
# `?(1)`为条件,当子表达式`1`匹配时条件成立,需要执行`)`匹配,也就是匹配右括号

(\()?test(?(1)\))

前后查找条件

条件为定义的首尾是否匹配,如果匹配,则继续执行后面的匹配.注意,首尾不包含在匹配的内容中.

# `?(?=-)`为前向查找条件,只有在以`-`为前向查找的结尾能匹配`\d{5}`才继续匹配`-\d{4}`
\d{5}(?(?=-)-\d{4})

常用的正则表达式

校验数字的表达式

# 1 数字
^[0-9]*$

# 2 n位的数字
^\d{n}$

# 3 至少n位的数字
^\d{n,}$

# 4 m-n位的数字
^\d{m,n}$

# 5 零和非零开头的数字
^(0|[1-9][0-9]*)$

# 6 非零开头的最多带两位小数的数字
^([1-9][0-9]*)+(.[0-9]{1,2})?$

# 7 带1-2位小数的正数或负数
^(-)?\d+(.\d{1,2})?$`

# 8 正数、负数、和小数
^(-|+)?\d+(.\d+)?$

# 9 有两位小数的正实数
^[0-9]+(.[0-9]{2})?$

# 10 有1~3位小数的正实数
^[0-9]+(.[0-9]{1,3})?$

# 11 非零的正整数
^[1-9]\d$
^([1-9][0-9]){1,3}$
^+?[1-9][0-9]*$

# 12 非零的负整数
^-[1-9][0-9]$
^-[1-9]\d$

# 13 非负整数
^\d+$
^[1-9]\d*|0$

# 14 非正整数
^-[1-9]\d*|0$
^((-\d+)|(0+))$

# 15 非负浮点数
^\d+(.\d+)?$
^[1-9]\d.\d|0.\d[1-9]\d|0?.0+|0$

# 16 非正浮点数
^((-\d+(.\d+)?)|(0+(.0+)?))$
^(-([1-9]\d.\d|0.\d[1-9]\d))|0?.0+|0$

# 17 正浮点数
^[1-9]\d.\d|0.\d[1-9]\d$
^(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9]))$

# 18 负浮点数
^-([1-9]\d.\d|0.\d[1-9]\d)$
^(-(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9])))$

# 19 浮点数
^(-?\d+)(.\d+)?$
^-?([1-9]\d.\d|0.\d[1-9]\d|0?.0+|0)$

校验字符的表达式

# 1 汉字
^[\u4e00-\u9fa5]{0,}$

# 2 英文和数字
^[A-Za-z0-9]+$
^[A-Za-z0-9]{4,40}$

# 3 长度为3-20的所有字符
^.{3,20}$

# 4 由26个英文字母组成的字符串
^[A-Za-z]+$

# 5 由26个大写英文字母组成的字符串
^[A-Z]+$

# 6 由26个小写英文字母组成的字符串
^[a-z]+$

# 7 由数字和26个英文字母组成的字符串
^[A-Za-z0-9]+$

# 8 由数字、26个英文字母或者下划线组成的字符串
^\w+$
^\w{3,20}$

# 9 中文、英文、数字包括下划线
^[\u4E00-\u9FA5A-Za-z0-9_]+$

# 10 中文、英文、数字但不包括下划线等符号
^[\u4E00-\u9FA5A-Za-z0-9]+$
^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$

# 11 禁止输入含有~的字符
[^~\x22]+

特殊需求表达式


# 1 Email地址
^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$

# 2 域名
[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?

# 3 InternetURL
[a-zA-z]+://[^\s]
^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=])?$

# 4 手机号码
^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$

# 5 电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX")
^((\d{3,4}-)|\d{3.4}-)?\d{7,8}$

# 6 国内电话号码(0511-4405222、021-87888822)
\d{3}-\d{8}|\d{4}-\d{7}

# 7 身份证号(15位、18位数字)
^\d{15}|\d{18}$

# 8 短身份证号码(数字、字母x结尾)
^([0-9]){7,18}(x|X)?$
^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$

# 9 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线)
^[a-zA-Z][a-zA-Z0-9_]{4,15}$

# 10 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线)
^[a-zA-Z]\w{5,17}$

# 11 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间)
^(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,10}$

# 12 日期格式
^\d{4}-\d{1,2}-\d{1,2}

# 13 一年的12个月(01~09和1~12)
^(0?[1-9]|1[0-2])$

# 14 一个月的31天(01~09和1~31)
^((0?[1-9])|((1|2)[0-9])|30|31)$

# 15 xml文件
^([a-zA-Z]+-?)+[a-zA-Z0-9]+\.[x|X][m|M][l|L]$

# 16 中文字符的正则表达式
[\u4e00-\u9fa5]

# 17 双字节字符
# 包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
[^\x00-\xff]

# 18 空白行的正则表达式
# 可以用来删除空白行
\n\s*\r

# 19 HTML标记的正则表达式
<(\S?)[^>]>.?|<.?/>

# 20 首尾空白字符的正则表达式
# 可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式
^\s|\s$或(^\s)|(\s$)

# 21 腾讯QQ号
# 腾讯QQ号从10000开始
[1-9][0-9]{4,}

# 22 中国邮政编码
# 中国邮政编码为6位数字
[1-9]\d{5}(?!\d)

# 23 IP地址
# 提取IP地址时有用
\d+.\d+.\d+.\d+
((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))

文章作者: darebeat
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 darebeat !
 上一篇
SHELL命令-envsubst SHELL命令-envsubst
通常我们需要获取某一个或者几个环境去替换系统中的某些变量,这种情况下我们只需使用sed去简单的替换掉即可,在这种场景中,sed就可以满足我们的需求,但是如果我们需要修改的变量较多,而且不确定到底有哪些变量时,envsubst就排上了用场。
2020-12-30
下一篇 
树莓派-系统配置 树莓派-系统配置
树莓派官方深度定制的硬件驱动与软件程序,官方推荐系统。
2020-12-23
  目录