当前位置: 首页 > news >正文

正则表达式入门到精通教程(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 进行测试。

http://www.dtcms.com/a/515716.html

相关文章:

  • 逆向开发在逆向加密狗中的作用
  • 网站模板 古典大学生app开发创业计划书
  • Linux 信号控制
  • Android Studio模拟器无法联网(能打开IP网页,但不能打开域名,DNS解析错误)问题2025年10月22日
  • php如何做局域网的网站网站设计与网页制作代码大全
  • 在没有网络的环境下安装包pymysql
  • Gradle 构建脚本迁移:从 Groovy DSL 到 Kotlin DSL,语法与技巧对比
  • 个人网站审批怎么制作ppt模板 教程
  • 内网构建https
  • [运维]宝塔 Apache环境使用CDN获取访客真实IP方法
  • 【学习系列】SAP RAP 17:RAP应用部署集成至Fiori Launchpad 【S4HC Public Edition】
  • 正点原子RK3568学习日志15-杂项设备驱动
  • 绍兴建设开发有限公司网站网站网站娱乐建设
  • 迭代器失效问题
  • Ubuntu 16.04交叉编译arm-linux-gnueabihf的QT5.6.2
  • 神经网络详解
  • 网站如何防止黑客攻击宁波新闻
  • 为打印预览对话框 PrintPreviewDialog 添加保存到 PDF 文件按钮源代码详解
  • Nevercenter CameraBag Photo for mac照片滤镜美化软件
  • 设计模式-策略模式:从鞋厂促销活动看算法的灵活切换
  • Java实现Excel转PDF
  • Fenwick 树进行快速统计
  • Cocos creator2.4.4 处理 16KB 问题
  • 旅游网站的设计的前提成都那家网站做的好
  • undefined reference to `cv::String::dea llocate()‘
  • 计划任务原理及实战
  • 做网站设计最好的公司做旅游网站的论文
  • 【Android】Handler/Looper机制相关的类图和流程图
  • ARM《1》_回顾gcc、动态编译和静态编译、MakeFile的使用
  • 网络环路:隐形威胁的破解之道