正则表达式入门到精通教程(Linux实操版)

一、为什么你必须学会正则表达式

想象一下,你刚接手一个服务器日志文件,老板让你找出所有来自 404 错误的 IP 地址。如果没有正则表达式,你可能需要手动翻阅成千上万行文本;而掌握正则表达式后,一条命令就能搞定。正则表达式就像一把文本处理的瑞士军刀,在 Linux 系统管理、日志分析、数据清洗等场景中不可或缺。本教程将带你从零基础开始,通过实际 Linux 命令示例,逐步掌握这门强大的技能。

1.1 正则表达式到底是什么

正则表达式(Regular Expression)是一种用于匹配文本模式的工具,它不是某个编程语言的专属特性,而是一种通用的文本处理规则。你可以把它理解为一种文本搜索语言,用特定的符号组合来描述你想要匹配的字符串特征。

在 Linux 系统中,几乎所有文本处理工具都支持正则表达式,比如 grep、sed、awk、vim 等。掌握正则表达式,就相当于掌握了 Linux 文本处理的"核心密码"。

二、基础语法:从简单匹配开始

2.1 普通字符匹配

最基本的正则表达式就是直接使用文本字符进行匹配。比如你想在文件中查找包含 "error" 的行,可以直接使用:

复制代码
# 在 example.log 文件中查找包含 "error" 的行
grep "error" example.log

# 示例输出(假设 example.log 内容):
# 2025-10-20 14:30:02 ERROR connection failed
# 2025-10-20 14:35:10 WARNING disk space low, error may occur

这里的 "error" 就是一个最简单的正则表达式,它会精确匹配包含这个字符串的所有行。

2.2.1特殊字符与转义

有些字符在正则表达式中具有特殊含义,比如 . * + ? | ( ) [ ] { } ^ $ \。如果需要匹配这些字符本身,必须使用反斜杠 \ 进行转义。

复制代码
# 匹配包含 "file.txt" 的行(. 是特殊字符,需要转义)
grep "file\.txt" example.log

# 错误示例(不转义会匹配 "fileAtxt" "file1txt" 等)
grep "file.txt" example.log  # 这会匹配 "fileXtxt" 形式的字符串

2.2 核心匹配规则

2.2.1 匹配任意字符:.

点号 . 可以匹配除换行符外的任意单个字符。

复制代码
# 创建测试文件
echo -e "cat\ncot\ncut\ncar\nc3t" > test.txt

# 匹配 "c" 开头,"t" 结尾,中间任意一个字符的行
grep "c.t" test.txt

# 输出结果:
# cat
# cot
# cut
# c3t
# 解释:. 匹配了 a、o、u、3 这些不同的字符

2.2.2匹配多个字符:*

星号 * 表示匹配前面的元素零次或多次。

复制代码
# 匹配 "ca" 后面跟任意多个 "t" 的行
grep "cat*" test.txt

# 输出结果:
# cat
# 解释:* 匹配了 "t" 一次;如果有 "ca" 或 "catt" 也会被匹配

2.2.3 匹配边界:^ 和 $

^ 匹配行的开始,$ 匹配行的结束。

复制代码
# 匹配以 "c" 开头的行
grep "^c" test.txt

# 匹配以 "t" 结尾的行
grep "t$" test.txt

# 匹配空行(开始即结束,中间没有任何字符)
grep "^$" test.txt

2.2.4 字符集:[ ]

方括号 [] 用于指定一个字符集合,匹配其中任意一个字符。

复制代码
# 匹配 "c" 开头,"t" 结尾,中间是 a、o 或 u 的行
grep "c[auo]t" test.txt

# 输出结果:
# cat
# cot
# cut
# 解释:[auo] 只匹配 a、u、o 这三个字符

# 匹配数字开头的行
grep "^[0-9]" data.log

# 匹配非数字开头的行(^ 在 [] 内表示取反)
grep "^[^0-9]" data.log

字符集支持范围表示法,例如 [a-z] 匹配所有小写字母,[0-9] 匹配所有数字,[A-Za-z0-9] 匹配所有字母和数字。

复制代码
# 匹配 "user" 后面跟 1-3 位数字的行
grep "user[0-9]" test.txt       # 1 位数字
grep "user[0-9][0-9]" test.txt  # 2 位数字

2.2.5 重复次数:{n,m}

花括号 {} 用于指定元素的重复次数。注意在基本正则表达式(BRE)中需要转义,如 \{n,m\}。

复制代码
# 匹配 "a" 出现 2-3 次的行(使用 grep -E 启用扩展正则表达式)
echo -e "aa\naaa\naaaa\na" | grep -E "a{2,3}"

# 输出结果:
# aa
# aaa
# 解释:{2,3} 表示匹配 2 到 3 个 "a"

# 基本正则表达式版本(需要转义花括号)
echo -e "aa\naaa\naaaa\na" | grep "a\{2,3\}"

2.2.6 或逻辑:|

竖线 | 表示逻辑"或",匹配两边任意一个表达式。在 grep 中需要使用 -E 参数启用扩展正则表达式。

复制代码
# 匹配包含 "error" 或 "warning" 的行
grep -E "error|warning" system.log

# 等价于基本正则表达式(需要转义 |)
grep "error\|warning" system.log

2.2.7 分组匹配:( )

圆括号 () 用于将多个元素组合为一个单元,可以与 * + ? | 等结合使用。在 grep 中需要 -E 参数。

复制代码
# 匹配 "cat" 或 "dog" 开头的行
grep -E "^(cat|dog)" test.txt

# 匹配 "re" 或 "un" 开头,后面跟 "do" 的行
grep -E "^(re|un)do" words.txt

三、Linux 三剑客实战

3.1 grep:文本搜索利器

grep 是最常用的文本搜索工具,支持基本正则表达式(默认)和扩展正则表达式(-E 参数)。

常用参数:

  • -i:忽略大小写

  • -v:反向匹配(不包含模式的行)

  • -n:显示行号

  • -r:递归搜索目录

  • -A N:显示匹配行及其后 N 行

  • -B N:显示匹配行及其前 N 行

  • -C N:显示匹配行及其前后 N 行

    在 /var/log 目录下递归搜索包含 "error" 的日志文件

    grep -rni "error" /var/log

    查找不包含 "debug" 的行并显示行号

    grep -nv "debug" app.log

    显示匹配行及其前后 2 行上下文

    grep -C 2 "critical" server.log

3.2 sed:流编辑器

sed 主要用于文本替换,支持正则表达式匹配和修改。

基本语法:sed 's/原模式/替换文本/选项' 文件名

复制代码
# 创建测试文件
echo "Hello world! This is a test. Test is important." > sedtest.txt

# 替换第一个 "test" 为 "example"(只替换每行第一个匹配)
sed 's/test/example/' sedtest.txt

# 替换所有 "test"(忽略大小写)
sed 's/test/example/gi' sedtest.txt

# 替换并直接修改文件(-i 参数,强烈建议先备份)
sed -i.bak 's/Hello/Hi/' sedtest.txt  # 会生成 sedtest.txt.bak 备份

# 使用正则表达式删除空行
sed '/^$/d' input.txt > output.txt

# 替换以 "Error" 开头的行为空行
sed '/^Error/d' log.txt

3.3 awk:文本分析工具

awk 适合处理结构化文本,支持更复杂的正则表达式匹配和数据处理。

复制代码
# 创建测试数据文件
echo -e "name,age,city\nAlice,25,NewYork\nBob,30,London\nCharlie,35,Paris" > data.csv

# 使用逗号分隔,打印第一列和第三列(姓名和城市)
awk -F ',' '{print $1, $3}' data.csv

# 匹配 age 大于 28 的行
awk -F ',' '$2 > 28 {print $0}' data.csv

# 使用正则表达式匹配城市以 "N" 开头的行
awk -F ',' '$3 ~ /^N/ {print $1}' data.csv  # ~ 表示匹配正则表达式

# 统计包含 "error" 的行数
awk '/error/ {count++} END {print "Total errors:", count}' server.log

四、进阶技巧

4.1 贪婪匹配与非贪婪匹配

正则表达式默认是贪婪匹配(尽可能匹配最长的字符串),在扩展正则表达式中,可以使用 *? +? ?? {n}? 实现非贪婪匹配(尽可能匹配最短的字符串)。

复制代码
# 创建测试文件
echo "<div>content1</div><div>content2</div>" > html.txt

# 贪婪匹配(默认):会匹配从第一个 <div> 到最后一个 </div> 的所有内容
grep -Eo "<div>.*</div>" html.txt
# 输出:<div>content1</div><div>content2</div>

# 非贪婪匹配:只匹配第一个 <div>...</div>
grep -Eo "<div>.*?</div>" html.txt
# 输出:<div>content1</div>

4.2 零宽断言

零宽断言用于匹配某个位置前后的内容,而不包含该位置本身。常见的有:

  • (?=pattern):正向先行断言(后面必须跟着 pattern)

  • (?!pattern):负向先行断言(后面不能跟着 pattern)

  • (?<=pattern):正向后行断言(前面必须是 pattern)

  • (?<!pattern):负向后行断言(前面不能是 pattern)

注意:grep 不支持零宽断言,需要使用 egrep 或其他工具如 perl。

复制代码
# 匹配 "price" 后面跟着数字的行(但不包含数字本身)
echo -e "price100\npriceabc\ncost200" | perl -ne '/price(?=\d)/ && print'
# 输出:price100

# 匹配 "123" 前面不是 "abc" 的行
echo -e "abc123\ndef123\nx123" | perl -ne '/(?<!abc)123/ && print'
# 输出:def123
# x123

4.3 正则表达式的组合使用

实际应用中通常需要组合多种规则来完成复杂匹配任务。

复制代码
# 匹配邮箱地址的正则表达式
# 规则:用户名@域名.后缀,用户名可包含字母、数字、点、下划线、连字符
grep -Eo '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}' emails.txt

# 解释:
# [A-Za-z0-9._%+-]+ : 匹配用户名部分(至少一个字符)
# @ : 匹配 @ 符号
# [A-Za-z0-9.-]+ : 匹配域名主体
# \. : 匹配点号(域名和后缀之间的点)
# [A-Za-z]{2,} : 匹配后缀(至少 2 个字母,如 com, org, cn 等)

五、实战案例

案例 1:分析 Nginx 访问日志

假设我们有 Nginx 访问日志 access.log,格式如下:

复制代码
192.168.1.1 - - [22/Oct/2025:10:00:01 +0800] "GET /index.html HTTP/1.1" 200 1234
10.0.0.5 - - [22/Oct/2025:10:00:05 +0800] "POST /api/login HTTP/1.1" 401 567
192.168.1.1 - - [22/Oct/2025:10:00:10 +0800] "GET /images/logo.png HTTP/1.1" 200 9876

任务 1:提取所有 404 错误的 IP 地址

复制代码
# 匹配状态码为 404 的行,提取 IP 地址(第一个字段)
awk '$9 == 404 {print $1}' access.log

# 统计每个 IP 出现的次数(排序并去重)
awk '$9 == 404 {print $1}' access.log | sort | uniq -c | sort -nr

任务 2:找出访问次数最多的前 10 个 IP

复制代码
# 提取所有 IP 地址,统计次数并排序
awk '{print $1}' access.log | sort | uniq -c | sort -nr | head -10

案例 2:处理 CSV 数据

假设我们有一个不规范的 CSV 文件 data.csv,需要清洗数据:

复制代码
name,age,email,phone
Alice,25,alice@example.com,123-456-7890
Bob,30,bob@test, (987) 654-3210
Charlie,35,,555.123.4567

任务:提取有效的邮箱和电话号码

复制代码
# 提取有效的邮箱地址
grep -Eo '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}' data.csv

# 提取电话号码(支持多种格式)
grep -Eo '(\+?\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}' data.csv

# 使用 awk 处理整行数据,过滤掉邮箱为空的行
awk -F ',' '$3 != "" {print $1 "," $3}' data.csv

案例 3:批量重命名文件

假设目录中有多个图片文件,命名格式不统一:

复制代码
image1.jpg
pic_2.png
photo-3.gif
img_04.bmp

任务:统一重命名为 img_01.jpg, img_02.png 格式

复制代码
# 使用 rename 命令(需要先安装,不同系统版本语法可能不同)
# Ubuntu/Debian 版本
rename 's/^(image|pic_|photo-|img_)(\d+)\.(jpg|png|gif|bmp)$/img_0$2.$3/' *

# 如果数字超过 10,使用更复杂的正则表达式
rename 's/^(image|pic_|photo-|img_)(\d+)\.(jpg|png|gif|bmp)$/sprintf("img_%02d.%s", $2, $3)/e' *

六、常见问题与注意事项

6.1 正则表达式引擎差异

不同工具使用的正则表达式引擎可能不同,主要分为:

  • 基本正则表达式(BRE):grep 默认模式

  • 扩展正则表达式(ERE):grep -E, egrep, awk

  • Perl 兼容正则表达式(PCRE):grep -P, perl

主要差异:BRE 中 { } ? | ( ) 需要转义,ERE 和 PCRE 不需要。

复制代码
# BRE 语法(需要转义)
grep "a\{2,3\}" file.txt

# ERE 语法(不需要转义)
grep -E "a{2,3}" file.txt

6.2 性能优化

处理大文件时,正则表达式的效率很重要:

  • 避免过度复杂的表达式

  • 尽量使用锚点 ^ 和 $ 减少不必要的匹配

  • 使用更具体的字符集代替通配符 .

    低效:无锚点,全文件扫描

    grep "error" large.log

    高效:有锚点,只匹配行首

    grep "^Error" large.log

6.3 测试与调试

编写复杂正则表达式时,建议先在小样本上测试:

  • 使用在线工具如 regex101.com 验证表达式

  • 在命令行中先使用 grep -o 查看实际匹配内容

  • 逐步构建表达式,不要一次性写复杂模式

七、学习资源与进阶路径

7.1 推荐工具

  • 在线测试工具:Regex101(支持多种引擎和实时解释)

  • Linux 工具:grep, sed, awk, perl, vim

  • 文本编辑器插件:VS Code Regex Previewer, Sublime Text Regex Helper

7.2 进阶学习方向

  1. PCRE 高级特性:学习 Perl 兼容正则表达式的高级功能

  2. 正则表达式优化:学习如何编写高效的正则表达式

  3. 编程语言集成:在 Python, JavaScript 等语言中使用正则表达式

  4. 语法分析:结合语法规则解析更复杂的文本结构

八、总结

正则表达式是文本处理的强大工具,掌握它可以极大提高你的工作效率。从简单的字符匹配到复杂的文本分析,正则表达式都能胜任。学习正则表达式的关键是理解基本语法,然后通过大量实践积累经验。

记住,即使是正则表达式专家也需要不断查阅文档和测试表达式。不要害怕犯错,正则表达式就是在不断试错中逐渐掌握的技能。现在就打开你的终端,尝试用今天学到的知识处理实际问题吧!

九、练习题

  • 编写一个正则表达式,匹配所有以字母开头,后面跟字母、数字和下划线的字符串(变量名)。

  • 使用 grep 命令找出系统日志中过去 24 小时内的所有错误信息。

  • 使用 sed 命令将文件中所有的 tab 字符替换为 4 个空格。

  • 使用 awk 统计 Apache 访问日志中每个 HTTP 状态码的出现次数。

  • 编写一个正则表达式,匹配中国大陆的手机号码(11 位数字,以 1 开头)。

答案可以在网上搜索验证,或者使用 regex101.com 进行测试。

相关推荐
LaughingZhu2 分钟前
Product Hunt 每日热榜 | 2026-04-30
人工智能·经验分享·深度学习·神经网络·产品运营
sunneo7 分钟前
专栏D-团队与组织-03-产品文化
人工智能·产品运营·aigc·产品经理·ai编程
Muyuan19987 分钟前
28.Paper RAG Agent 开发记录:修复 LLM Rerank 的解析、Fallback 与可验证性
linux·人工智能·windows·python·django·fastapi
比昨天多敲两行20 分钟前
Linux进程概念
linux·运维·服务器
小呆呆66621 分钟前
Codex 穷鬼大救星
前端·人工智能·后端
薛定猫AI26 分钟前
【深度解析】Kimi K2.6 的长上下文 Agentic Coding 能力与 OpenAI 兼容 API 接入实践
人工智能·自动化·知识图谱
星爷AG I29 分钟前
20-6 记忆整合(AGI基础理论)
人工智能·agi
AI创界者31 分钟前
人工智能 GPT-Image DMXAPI Python AI绘画
人工智能
HLC++35 分钟前
Linux的基本指令+权限+基础开发工具
linux·运维·服务器
一拳一个娘娘腔35 分钟前
红队与蓝队视角:现代网络安全攻防中的Linux命令深度解析
linux·安全