正则表达式Regular Expression

不同版本

  • POSIX基本 - Basic Regular Expression(BRE)
  • POSIX扩展 - Extended Regular Expression(ERE)
  • Perl兼容正则表达式(PCRE)
  • 其他版本(Python、Java等)

版本问题:

Linux中的grep、sed和awk都是基于POSIX标准的BRE或ERE,对于一些现代的正则表达式是不支持的。

在使用正则表达式时,匹配不到想要的结果,可能不是写错了,而是版本不支持此特性。

例如grep的-P参数,表示可以使用PCRE。

基本语法

/([A-Z])\W+/g

正则表达式一般是用两个斜线来包裹起来的,后面可以跟上一些修饰符,比如这里的g就表示global(全局匹配)

i:表示忽略字母大小写

m:表示多行匹配

# 匹配到所有的小写字母a
/a/g
# 匹配到所有的at
/at/g
# 匹配at后面加上任意一个字符,这个.可以放在任意位置,表示那个位置的字符任意
/at./g
# 匹配atc和ate、at0 下面默认把修饰符和斜线去掉了
at[ce0]
# 匹配到at后面跟上a到z的所有小写字母
at[a-z]
# 匹配到at1 at2 at3和后面跟着一个任意大小写字母的
at[a-zA-Z1-3]
# 匹配到at除了后面跟上a到z的所有小写字母,^放在方括号内部表示取反,放在外部表示取每行的开头
at[^a-z]

预定义字符类(匹配一些常见的字符)

\d等价于[0-9]

\D表示非数字

\w表示字母数字和下划线_

\W表示与小写的范围相反

\s表示空白字符:空格或者Tab

位置和边界匹配

# 匹配到以a开头的行,m是多行匹配的意思,在VScode或vi编辑器中是不需要(默认是多行匹配)
/^a/gm

# 与^对应的是$,它表示匹配每一行的结尾
# 匹配到以英文句号结尾的行,(.)号是一个特殊字符,表示除了换行符之外的任意字符,如果想只当普通句号去用,需要加一个\去转义它
/\.$/gm

# 以in开头的部分被高亮
\bin

# 以in结尾的部分被高亮
in\b

# 匹配到独立的in
\bin\b

# 匹配非单词边界,就只有在单词中间的in被匹配到,而开头结尾或者独立的in不会匹配
\Bin\B

量词

# +表示前面的字符重复了一次或多次
# atttttt atttttttttttttttttttttt
at+

# *表示前面的字符n次(含零次)都会匹配到
at*

# ?表示前面的字符重复了一次或零次
# 只有a或者at才会被匹配到
at?

# {N}表示规定重复次数
# attt会被匹配到
at{3}

# {N,M}表示规定重复次数是N-M次
# attt atttt attttt
at{3,5}

# 如果只有{N,}没有规定M,表示至少重复了N次以上
# 这里是贪婪匹配:尽可能多的去匹配
at{3,}
# 非贪婪模式:只需要满足最小的匹配条件就可以
# 无论attttttttttttttttt后面有多少个t,只匹配到attt就停
at{3,}?

分组和引用

at*只能匹配到a后面n个t的情况,那么想要匹配到atatat这样的呢?

# 匹配n个at
(at)*

# 匹配3个at
(at){3}

# 同时匹配Pattern和pattern
1.Pattern|pattern 麻烦
2.[Pp]attern
3.(P|p)attern

分组

先给一组日期
2024-05-01
2024-05-02
2024-05-03

第一步:匹配日期
\d{4}-\d{1,2}-\d{1,2}
第二步:捕获分组
(\d{4})-(\d{1,2})-(\d{1,2})
   1        2         3
第三步:替换,把分组后的内容按照2-3-1调位置
$2-$3-$1
结果:
05-01-2024
05-02-2024
05-03-2024
再给一组日期,使用不同的连接符
2024-05-01
2024/05/02
2024_05_03
2024.05.04
20240505
2024_05_03
2024.05.04
20240505

捕获
(\d{4})[-/_.]?(\d{1,2})[-/_.]?(\d{1,2}) # ?表示前面的字符重复了一次或零次

(\d{4})[-/_.]?(?:\d{1,2})[-/_.]?(\d{1,2}) # 由于月份分组前加了个?:这就变成了一个非捕获分组(只有分组能力而不捕获为一个真正的组)
   1                                2

引用

给几个单词
alibaba
tencent
google
baidu

# \1表示引用定义第一个的分组
([a-z])[a-z]*\1
会匹配到
alibaba
tencent
goog

# 不想匹配到goog,设置单词边界
\b([a-z])[a-z]*\1\b
会匹配到
alibaba
tencent

前瞻和后顾(高级用法)

包含,正向前瞻、负向前瞻、正向后顾、负向后顾。

简单讲就是,它可以让我们匹配到字符的前面或后面,并不包括字符本身。

$100
$200
$abc
$def
# 前瞻是匹配到某些字符前面的内容
# 正向前瞻(?=)
\$(?=\d+)
会匹配到
$100
$200的$符

# 负向前瞻(?!)
\$(?!\d+)
会匹配到
$abc
$def的$符

# 后顾匹配到某些字符后面的内容
# 正向后顾(?<=)
(?<=\$)\d+
会匹配到
100
200

# 负向后顾(?<!) 也就是当前面的内容不是$时才会匹配到后面的数字
会匹配到
100
200中的00

1ce3ing
1 声望0 粉丝

运维充电,努力成为一个运开。