Linux 正则表达式详解(基础 + 扩展 + 实操)
Linux 正则表达式详解(基础 + 扩展 + 实操)
正则表达式(Regular Expression,简称 RE)是 Linux 文本处理的核心工具,用于定义字符匹配模式,配合 grep
、sed
、awk
等工具可实现文本过滤、查找、替换等操作。本文将从概念、基础正则、扩展正则、特殊字符组四个维度,结合实操案例完整讲解
一、正则表达式概述
1. 核心概念
正则表达式是模式模板,Linux 工具通过该模板对数据流进行 “匹配筛选”:
- 匹配的数据:被工具接受并进一步处理(如输出、替换)
- 不匹配的数据:被直接滤除
本质:通过 “普通字符 + 元字符” 的组合,描述字符串的排列规则,实现对文本的分割、匹配、查找、替换
2. 构成与作用
构成部分 | 说明 | 示例 |
---|---|---|
普通字符 | 无特殊含义的字符(字母、数字、标点) | a 、1 、! 、- |
元字符 | 具有特殊匹配规则的专用字符 | ^ 、$ 、* 、[ ] |
核心作用:判断字符串是否符合指定格式(如 “是否为手机号”“是否为邮箱”),或从文本中提取特定格式的内容(如 “提取所有 IP 地址”)
3. 可实现的核心目标
- 匹配验证:判断字符串是否符合正则模式(如 “验证一行文本是否以
#
开头”) - 内容提取:从复杂文本中筛选出符合模式的部分(如 “从日志中提取所有错误代码”)
二、基础正则(Basic Regular Expression,BRE)
基础正则是正则的 “核心子集”,支持 grep
、sed
(基础模式)、awk
等工具,核心是掌握元字符的匹配规则
1. 基础正则核心元字符表
元字符 | 功能描述 | 示例 | 匹配效果 |
---|---|---|---|
\ | 转义字符:将特殊字符还原为普通字符 | \$ 、\! 、\n | 匹配 $ 、! 、换行符 |
^ | 匹配 “字符串开头” 的位置 | ^a 、^# | 匹配以 a 开头、以 # 开头的行 |
$ | 匹配 “字符串结尾” 的位置 | word$ 、3$ | 匹配以 word 结尾、以 3 结尾的行 |
^$ | 匹配 “空行”(开头到结尾无任何字符) | grep "^$" file.txt | 筛选文件中的所有空行 |
. | 匹配 “除换行符(\n)外的任意 1 个字符” | lo.k 、l..k | loak (1 个字符)、look (2 个字符) |
* | 匹配 “前面 1 个字符出现 0 次或多次” | lo*k | lk (o 出现 0 次)、lok (o1 次)、look (o2 次) |
[list] | 匹配 “list 列表中的任意 1 个字符” | go[ola]d 、[a-z0-9] | gold /goal /god 、任意小写字母或数字 |
[^list] | 匹配 “非 list 列表中的任意 1 个字符” | [^0-9] 、[^a-z] | 非数字、非小写字母 |
\{n\} | 匹配 “前面 1 个字符出现恰好 n 次” | lo\{2\}k 、[0-9]\{2\} | look (o2 次)、任意 2 位数字 |
\{n,\} | 匹配 “前面 1 个字符出现至少 n 次” | lo\{2,\}k 、[0-9]\{3,\} | look (o2 次)、loook (o3 次)、3 位及以上数字 |
\{n,m\} | 匹配 “前面 1 个字符出现n~m 次” | lo\{2,3\}k | look (o2 次)、loook (o3 次) |
注意:基础正则中,
{n}
/{n,}
/{n,m}
必须加转义符\
,否则会被当作普通字符处理
2. 基础正则实操案例
以下案例基于测试文件 a.txt
/b.txt
/c.txt
,先定义测试文件内容:
[root@syf ~]# vim a.txt
lk
lok
look
loook
looooook
loooooaaak
looooooook
abbbbcd
abbbbcd666
ooooloooook
oooooolk
aoblck
~
[root@syf ~]# vim b.txt
aaabd
cdd
cdc
cdd
~
[root@syf ~]# vim c.txt
lok
lo12k
lo1k
loAk
loBk
look
loak
lodk
abcd
1234
~
案例 1:*
匹配 “前面字符 0 次或多次”
# 匹配 "lo*k":o出现0次(lk)、1次(lok)、多次(look等)
[root@syf ~]# grep "lo*k" a.txt
lk # o出现0次
lok # o出现1次
look # o出现2次
loook # o出现3次
looooook # o出现5次
looooooook # o出现7次
ooooloooook # 中间含多个o
oooooolk # o出现6次# 匹配 "loo*k":o至少出现1次(排除lk)
[root@syf ~]# grep "loo*k" a.txt
lok # o出现1次
look # o出现2次
loook # o出现3次
looooook # o出现5次
looooooook # o出现7次
ooooloooook # 中间含多个o
案例 2:.
匹配 “任意 1 个字符”
# 匹配 "lo.*k":o后接“任意字符(0次或多次)”+k(.*表示任意字符任意次)
[root@syf ~]# grep "lo.*k" a.txt
lok # o后接0个字符
look # o后接1个o
loook # o后接2个o
looooook # o后接4个o
loooooaaak # o后接3个o+2个a
looooooook # o后接5个o
ooooloooook # 前面有o,中间含多个o# 匹配 "lo.k":o后接“恰好1个字符”+k
[root@syf ~]# grep "lo.k" a.txt
look # o后接1个o(lo+o+k)# 匹配 "l..k":l后接“恰好2个字符”+k
[root@syf ~]# grep "l..k" a.txt
look # l后接2个o(l+oo+k)
案例 3:\{n\}
/\{n,\}
/\{n,m\}
匹配 “固定次数”
# 匹配 "lo\{2\}k":o恰好出现2次
[root@syf ~]# grep "lo\{2\}k" a.txt
look # o出现2次# 匹配 "lo\{3\}k":o恰好出现3次
[root@syf ~]# grep "lo\{3\}k" a.txt
loook # o出现3次# 匹配 "lo\{3,\}k":o至少出现3次
[root@syf ~]# grep "lo\{3,\}k" a.txt
loook # o出现3次
looooook # o出现5次
looooooook # o出现7次
ooooloooook # 中间o出现5次# 匹配 "lo\{3,5\}k":o出现3~5次
[root@syf ~]# grep "lo\{3,5\}k" a.txt
loook # o出现3次
ooooloooook # 中间o出现5次(符合3~5次)
案例 4:^
/$
/^$
匹配 “开头 / 结尾 / 空行”
# 匹配 "^c":以c开头的行
[root@syf ~]# grep "^c" b.txt
cdd
cdc
cdd# 匹配 "d$":以d结尾的行
[root@syf ~]# grep "d$" b.txt
abd
cdd
cdd# 匹配 "^$":空行(输出为空行,对应b.txt中的空行)
[root@syf ~]# grep "^$" b.txt
(此处输出1行空行)
案例 5:[list]
/[^list]
匹配 “指定 / 非指定字符”
# 匹配 "lo[a-zA-Z0-9]k":o后接1个“字母/数字”+k
[root@syf ~]# grep "lo[a-zA-Z0-9]k" c.txt
lo1k # o后接数字1
loAk # o后接大写A
loBk # o后接大写B
look # o后接小写o
loak # o后接小写a
lodk # o后接小写d# 匹配 "lo[ABo]k":o后接A/B/o中的任意1个
[root@syf ~]# grep "lo[ABo]k" c.txt
loAk # A
loBk # B
look # o# 匹配 "lo[^a-zA-Z]k":o后接“非字母”(即数字/符号)
[root@syf ~]# grep "lo[^a-zA-Z]k" c.txt
lo1k # 非字母(数字1)# 匹配 "[^a-zA-Z]":包含“非字母”的行(数字/符号)
[root@syf ~]# grep "[^a-zA-Z]" c.txt
lo12k # 含数字1、2
lo1k # 含数字1
1234 # 全是数字
三、扩展正则(Extended Regular Expression,ERE)
扩展正则是基础正则的 “增强版”,新增了 +
、?
、()
、|
等元字符,且 {n}
/{n,}
/{n,m}
无需转义。支持工具:egrep
(grep -E
)、awk
、sed -r
(扩展模式)
1. 扩展正则核心元字符表
元字符 | 功能描述 | 示例 | 匹配效果 | ||
---|---|---|---|---|---|
+ | 匹配 “前面 1 个字符出现 1 次或多次”(比* 严格) | lo+k | 匹配 lok (1 次)、look (2 次),不匹配 lk | ||
? | 匹配 “前面 1 个字符出现 0 次或 1 次”(最多 1 次) | lo?k | 仅匹配 lk (0 次)、lok (1 次) | ||
() | 将括号内的字符视为 “1 个整体”(分组) | l(oo)+k | 匹配 look (oo1 次)、looook (oo2 次) | ||
` | ` | 逻辑 “或”:匹配多个模式中的任意 1 个 | `l(oo | ab)k` | 匹配 look (oo)、labk (ab) |
{n} | 同基础正则 \{n\} ,无需转义 | lo{2}k | 匹配 look (o2 次) | ||
{n,} | 同基础正则 \{n,\} ,无需转义 | lo{3,}k | 匹配 loook (o3 次)及以上 | ||
{n,m} | 同基础正则 \{n,m\} ,无需转义 | lo{3,5}k | 匹配 loook (o3 次)~looooook (o5 次) |
2. 扩展正则实操案例(基于 a.txt
)
案例 1:+
匹配 “前面字符 1 次及以上”
# 匹配 "lo+k":o至少1次(排除lk)
[root@syf ~]# egrep "lo+k" a.txt
lok # o1次
look # o2次
loook # o3次
looooook # o5次
looooooook # o7次
ooooloooook # 中间o5次
案例 2:?
匹配 “前面字符 0 次或 1 次”
# 匹配 "lo?k":o最多1次(仅lk、lok)
[root@syf ~]# egrep "lo?k" a.txt
lk # o0次
lok # o1次
oooooolk # 前面o6次,最后o0次(符合lo?k)
案例 3:()
分组匹配 “整体重复”
# 匹配 "l(oo)+k":将"oo"视为整体,至少重复1次
look # "oo"重复1次(l+oo+k)
looooook # "oo"重复2次(l+oo+oo+k)
looooooook # "oo"重复3次(l+oo+oo+oo+k)
案例 4:|
逻辑 “或” 匹配多模式
# 先添加测试行 "labk" 到 a.txt
[root@syf ~]# echo "labk" >> a.txt# 匹配 "l(oo|ab)k":匹配 "loo k" 或 "lab k"
[root@syf ~]# egrep "l(oo|ab)+k" a.txt
look # 匹配 "oo"
looooook # 匹配 "oo"(重复2次)
looooooook # 匹配 "oo"(重复3次)
labk # 匹配 "ab"
案例 5:{n}
/{n,}
/{n,m}
无需转义
# 匹配 "lo{3}k":o恰好3次(无需转义{3})
[root@syf ~]# egrep "lo{3}k" a.txt
loook # o3次# 匹配 "lo{3,}k":o至少3次
[root@syf ~]# egrep "lo{3,}k" a.txt
loook # o3次
looooook # o5次
looooooook # o7次
ooooloooook # 中间o5次# 匹配 "lo{3,5}k":o3~5次
[root@syf ~]# egrep "lo{3,5}k" a.txt
loook # o3次
ooooloooook # 中间o5次
四、特殊字符组(字符类)
为简化正则书写,Linux 提供了预定义字符组(又称 “字符类”),等价于基础正则中的某些字符集合,更易记忆和跨平台(避免不同编码的字符范围问题)
特殊字符组表
字符组 | 等价写法 | 描述 | 应用场景 |
---|---|---|---|
[[:alpha:]] | [a-zA-Z] | 匹配任意字母(大写 + 小写) | 提取纯字母内容 |
[[:alnum:]] | [a-zA-Z0-9] | 匹配任意字母或数字 | 提取账号、ID(仅字母数字) |
[[:blank:]] | [ \t] | 匹配空格或 Tab 键 | 查找含空格 / Tab 的行 |
[[:digit:]] | [0-9] | 匹配任意数字(0~9) | 提取手机号、IP 地址中的数字部分 |
[[:lower:]] | [a-z] | 匹配任意小写字母 | 转换为大写前的筛选 |
[[:upper:]] | [A-Z] | 匹配任意大写字母 | 转换为小写前的筛选 |
[[:print:]] | - | 匹配任意可打印字符(含空格、标点) | 排除不可见字符(如控制字符) |
[[:punct:]] | [!\"#$%&...] | 匹配任意标点符号 | 提取含标点的句子 |
[[:space:]] | [ \t\n\r...] | 匹配任意空白字符(空格、Tab、换行等) | 查找含空白字符的行 |
实操示例
# 1. 匹配含数字的行([[:digit:]] 等价于 [0-9])
[root@syf ~]# grep "[[:digit:]]" c.txt
lo12k
lo1k
1234# 2. 匹配纯字母的行([[:alpha:]]+ 表示“字母出现1次及以上”)
[root@syf ~]# egrep "^[[:alpha:]]+$" c.txt
lok
loAk
loBk
look
loak
lodk
abcd# 3. 匹配含标点的行([[:punct:]])
[root@syf ~]# echo 'Hello,World!' > d.txt
[root@syf ~]# grep "[[:punct:]]" d.txt
Hello, World! # 含逗号和感叹号
核心知识点总结
- 基础正则 vs 扩展正则:
- 基础正则:
{n}
/{n,}
/{n,m}
需转义(\{n\}
),无+
/?
/()
/|
- 扩展正则:
{n}
无需转义,支持+
/?
/()
/|
,工具用egrep
/sed -r
/awk
- 基础正则:
- 元字符优先级:
- 分组
()
> 次数*
/+
/?
/{n}
> 位置^
/$
> 逻辑|
- 分组
- 特殊字符组:优先使用
[[:digit:]]
而非[0-9]
,跨平台更稳定