Linux 正则表达式详解(基础 + 扩展 + 实操)

发布于:2025-09-13 ⋅ 阅读:(13) ⋅ 点赞:(0)

Linux 正则表达式详解(基础 + 扩展 + 实操)

正则表达式(Regular Expression,简称 RE)是 Linux 文本处理的核心工具,用于定义字符匹配模式,配合 grepsedawk 等工具可实现文本过滤、查找、替换等操作。本文将从概念、基础正则、扩展正则、特殊字符组四个维度,结合实操案例完整讲解

一、正则表达式概述

1. 核心概念

正则表达式是模式模板,Linux 工具通过该模板对数据流进行 “匹配筛选”:

  • 匹配的数据:被工具接受并进一步处理(如输出、替换)
  • 不匹配的数据:被直接滤除

本质:通过 “普通字符 + 元字符” 的组合,描述字符串的排列规则,实现对文本的分割、匹配、查找、替换

2. 构成与作用

构成部分 说明 示例
普通字符 无特殊含义的字符(字母、数字、标点) a1!-
元字符 具有特殊匹配规则的专用字符 ^$*[ ]

核心作用:判断字符串是否符合指定格式(如 “是否为手机号”“是否为邮箱”),或从文本中提取特定格式的内容(如 “提取所有 IP 地址”)

3. 可实现的核心目标

  1. 匹配验证:判断字符串是否符合正则模式(如 “验证一行文本是否以 # 开头”)
  2. 内容提取:从复杂文本中筛选出符合模式的部分(如 “从日志中提取所有错误代码”)

二、基础正则(Basic Regular Expression,BRE)

基础正则是正则的 “核心子集”,支持 grepsed(基础模式)、awk 等工具,核心是掌握元字符的匹配规则

1. 基础正则核心元字符表

元字符 功能描述 示例 匹配效果
\ 转义字符:将特殊字符还原为普通字符 \$\!\n 匹配 $!、换行符
^ 匹配 “字符串开头” 的位置 ^a^# 匹配以 a 开头、以 # 开头的行
$ 匹配 “字符串结尾” 的位置 word$3$ 匹配以 word 结尾、以 3 结尾的行
^$ 匹配 “空行”(开头到结尾无任何字符) grep "^$" file.txt 筛选文件中的所有空行
. 匹配 “除换行符(\n)外的任意 1 个字符” lo.kl..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
aa

abd
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} 无需转义。支持工具:egrepgrep -E)、awksed -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!  # 含逗号和感叹号

核心知识点总结

  1. 基础正则 vs 扩展正则
    • 基础正则:{n}/{n,}/{n,m} 需转义(\{n\}),无 +/?/()/|
    • 扩展正则:{n} 无需转义,支持 +/?/()/|,工具用 egrep/sed -r/awk
  2. 元字符优先级
    • 分组 () > 次数 */+/?/{n} > 位置 ^/$ > 逻辑 |
  3. 特殊字符组:优先使用 [[:digit:]] 而非 [0-9],跨平台更稳定