【Linux从入门到精通】第27篇:文本处理三剑客(上)——grep 正则表达式实战
目录
一、引言:从“找东西”说起
二、grep基础:从简单搜索开始
2.1 基本语法
2.2 常用基础选项
2.3 管道中的grep
三、正则表达式:从“搜文字”到“搜模式”
3.1 两种正则标准:BRE与ERE
3.2 基础元字符
3.3 扩展正则(grep -E)新增元字符
3.4 常用字符类
四、实战一:查找邮箱地址
五、实战二:查找IP地址
六、实战三:查找电话号码
七、grep的高级功能
7.1 上下文控制:找到后看周围内容
7.2 递归搜索:在整个目录中查找
7.3 统计匹配数量
7.4 精确匹配控制
八、grep实战组合技
8.1 实时监控特定错误
8.2 排除注释和空行(查看有效配置)
8.3 批量在所有配置文件中搜索
九、本篇小结
动手练习
十、下篇预告
一、引言:从“找东西”说起
在Windows或macOS下,你习惯按Ctrl+F在文档中搜索关键词。在Linux命令行下,这个操作对应的命令就是grep。
grep的名字来源于一个古老的编辑器命令:g/re/p(global / regular expression / print),意思是“全局搜索正则表达式并打印匹配行”。从名字就能看出它的核心能力:
搜索:在一堆文本中找到目标
正则表达式:不只是搜“固定文字”,还能搜“符合某种模式”的文字
打印:把匹配的行输出给你看
在运维和开发工作中,grep的出现频率极高——查日志、找配置、过滤进程、筛选数据,几乎无处不用。
二、grep基础:从简单搜索开始
2.1 基本语法
bash
grep [选项] '搜索模式' 文件名
最简单的用法:
bash
grep 'error' /var/log/syslog # 在日志中找包含error的行 grep 'root' /etc/passwd # 查看root用户信息 ps aux | grep nginx # 查看nginx相关进程
2.2 常用基础选项
| 选项 | 含义 | 示例 |
|---|---|---|
-i | 忽略大小写 | grep -i 'Error' app.log |
-v | 反向匹配(排除) | grep -v '^#' nginx.conf(排除注释行) |
-n | 显示行号 | grep -n 'error' app.log |
-c | 只显示匹配行数量 | grep -c '404' access.log |
-w | 匹配整个单词 | grep -w 'at' file(不会匹配cat/ate) |
-r | 递归搜索目录 | grep -r 'TODO' ./src/ |
-l | 只输出文件名 | grep -rl 'config' /etc/ |
--color | 高亮匹配内容 | grep --color 'error' app.log |
2.3 管道中的grep
grep最常用的姿势不是直接搜文件,而是作为管道中的过滤器:
bash
# 查看所有监听端口中的80端口 ss -tlnp | grep :80 # 查看ERROR级别的日志并高亮 tail -f /var/log/app.log | grep --color -i error # 查看nginx进程(排除grep自身) ps aux | grep nginx | grep -v grep
小技巧:
ps aux | grep nginx | grep -v grep这条命令经常出现。另一种写法是ps aux | grep [n]ginx——方括号让grep匹配nginx但grep进程本身的命令行是grep [n]ginx,不匹配,从而省掉一个grep -v。
三、正则表达式:从“搜文字”到“搜模式”
grep真正的威力来自正则表达式。正则表达式是一种描述字符串模式的语法,让你能搜索“形如邮箱”“形如IP地址”的内容,而不是具体文字。
3.1 两种正则标准:BRE与ERE
Linux中的grep支持两种正则语法:
| 标准 | 全称 | grep命令 | 特点 |
|---|---|---|---|
| BRE | Basic Regular Expression | grep(默认) | 老式标准,部分元字符需要转义 |
| ERE | Extended Regular Expression | grep -E或egrep | 现代标准,元字符直接使用 |
选择建议:始终使用grep -E(扩展正则)。BRE需要频繁加反斜杠转义,如\(、\)、\{、\},可读性差且容易出错。除非要兼容极老的Unix系统,否则直接用ERE。
3.2 基础元字符
| 元字符 | 含义 | 示例 | 匹配结果 |
|---|---|---|---|
. | 匹配任意单个字符 | h.t | hat, hit, h3t |
* | 前一个字符重复0次或多次 | ab*c | ac, abc, abbc |
^ | 行首 | ^error | 以error开头的行 |
$ | 行尾 | error$ | 以error结尾的行 |
[] | 字符集合中的任意一个 | [Bb]ash | Bash, bash |
[^] | 不在集合中的任意一个 | [^0-9] | 非数字字符 |
\ | 转义字符 | \. | 匹配真正的点号 |
3.3 扩展正则(grep -E)新增元字符
| 元字符 | 含义 | 示例 |
|---|---|---|
+ | 前一个字符重复1次或多次 | ab+c→ abc, abbc(不匹配ac) |
? | 前一个字符重复0次或1次 | colou?r→ color, colour |
| | 或(分支) | error|warn→ 包含error或warn的行 |
() | 分组 | (error|warn) log→ error log或warn log |
{n} | 前一个字符重复恰好n次 | [0-9]{3}→ 三位数字 |
{n,} | 前一个字符重复n次及以上 | [0-9]{3,}→ 至少三位数字 |
{n,m} | 前一个字符重复n到m次 | [0-9]{2,4}→ 两到四位数字 |
3.4 常用字符类
| 写法 | 含义 | 等价写法 |
|---|---|---|
[0-9] | 数字 | [[:digit:]] |
[a-zA-Z] | 字母 | [[:alpha:]] |
[a-zA-Z0-9] | 字母数字 | [[:alnum:]] |
[ \t] | 空白字符 | [[:space:]] |
[A-Z] | 大写字母 | [[:upper:]] |
[a-z] | 小写字母 | [[:lower:]] |
POSIX字符类的优势:[[:digit:]]比[0-9]更规范,且在不同locale下行为一致。在写复杂脚本时推荐使用。
四、实战一:查找邮箱地址
bash
grep -E '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' file.txt模式拆解:
| 部分 | 含义 |
|---|---|
[a-zA-Z0-9._%+-]+ | 用户名部分:字母/数字/特殊符号,至少1个字符 |
@ | 必须的@符号 |
[a-zA-Z0-9.-]+ | 域名部分:字母/数字/点/短横线,至少1个字符 |
\. | 转义的点号(分隔域名和后缀) |
[a-zA-Z]{2,} | 顶级域名:至少2个字母 |
验证:
bash
echo "联系admin@example.com或support@my-site.org获取帮助" | \ grep -E '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'五、实战二:查找IP地址
IPv4地址由4组0-255的数字组成:
bash
grep -E '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' file.txt逐组拆解:
| 部分 | 匹配范围 |
|---|---|
25[0-5] | 250-255 |
2[0-4][0-9] | 200-249 |
[01]?[0-9][0-9]? | 0-199(灵活处理前导零) |
\. | 点号分隔符 |
{3} | 前三组重复3次 |
| 最后重复一组 | 第四组数字(结束) |
边界控制说明:上述模式会把
992.168.1.100这样的字符串从第2位开始截取匹配。如果需要精确校验整行内容(拒绝嵌入数字的IP),可以加\<和\>单词边界锚定,或用grep -w。一般grep从日志中提取IP时,周围有限定符号(空格、引号等),前述模式已足够实用。
六、实战三:查找电话号码
匹配中国手机号码(1开头的11位数字):
bash
grep -E '\b1[3-9][0-9]{9}\b' file.txt模式拆解:
\b:单词边界,防止匹配长数字串中间的部分1:开头必须是1[3-9]:第二位是3-9(覆盖所有运营商的号段)[0-9]{9}:后面接9位数字\b:单词边界结束
七、grep的高级功能
7.1 上下文控制:找到后看周围内容
匹配到目标行后,往往需要看周围的几行来理解上下文。
bash
# 查看匹配行及之后3行(找错误日志时特别有用,看错误之后发生了什么) grep -A 3 'FATAL' app.log # 查看匹配行及之前2行(查看错误发生前系统在做什么) grep -B 2 'FATAL' app.log # 查看匹配行前后各5行(最常用,全面了解上下文) grep -C 5 'FATAL' app.log
7.2 递归搜索:在整个目录中查找
bash
# 在当前目录及所有子目录的.sh文件中搜索 grep -r 'TODO' . --include="*.sh" # 排除某些目录 grep -r 'function' ./src/ --exclude-dir={node_modules,vendor} # 只列出包含匹配的文件名 grep -rl 'config' /etc/7.3 统计匹配数量
bash
# 统计nginx日志中404的出现次数 grep -c ' 404 ' /var/log/nginx/access.log # 统计每个IP发起请求的次数(用到后续文章的工具) grep -oE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' access.log | sort | uniq -c | sort -rn | head
7.4 精确匹配控制
bash
# 只输出匹配的内容(而不是整行) echo "Server IP: 192.168.1.1" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' # 只显示匹配的文件名 grep -rl 'ERROR' /var/log/
-o选项的妙用:当你不需要看整行、只想要精确提取数据片段时,-o配合正则能高效抽取结构化数据,如从日志中提取所有IP地址。
八、grep实战组合技
8.1 实时监控特定错误
bash
tail -f /var/log/nginx/error.log | grep --color -E '500|502|503|504'
8.2 排除注释和空行(查看有效配置)
bash
grep -v '^\s*#' nginx.conf | grep -v '^\s*$'
8.3 批量在所有配置文件中搜索
bash
grep -rE 'server_name\s+example\.com' /etc/nginx/ --include="*.conf"
九、本篇小结
grep核心能力:搜索文本 + 正则模式匹配 + 管道过滤。
选项速查:
| 选项 | 作用 |
|---|---|
-E | 使用扩展正则(推荐) |
-i | 忽略大小写 |
-v | 反向匹配 |
-n | 显示行号 |
-c | 统计匹配数量 |
-A/-B/-C N | 显示匹配行前后N行 |
-r | 递归搜索目录 |
-o | 只输出匹配部分 |
-l | 只输出文件名 |
-w | 整词匹配 |
正则核心元字符:
| 字符 | 作用 | 示例 |
|---|---|---|
. | 任意单字符 | h.t |
* | 0~n次 | ab*c |
+ | 1~n次 | ab+c |
? | 0~1次 | colou?r |
^/$ | 行首 / 行尾 | ^error/error$ |
[] | 字符集合 | [0-9] |
() | 分组 | (error|warn) |
{n,m} | 重复n~m次 | [0-9]{2,4} |
动手练习
bash
# 1. 在/etc/passwd中查找所有使用/bin/bash的用户 grep '/bin/bash' /etc/passwd # 2. 统计nginx日志中404错误的数量 grep -c ' 404 ' /var/log/nginx/access.log # 3. 查看sshd配置(排除注释和空行) grep -vE '^\s*(#|$)' /etc/ssh/sshd_config # 4. 从日志中提取所有IP地址 grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head # 5. 在shell脚本中搜索所有函数定义 grep -rnE '^[a-zA-Z_][a-zA-Z0-9_]*\s*\(\)' ~/scripts/十、下篇预告
grep擅长查找文本,但找到之后如果要做替换(比如批量修改配置文件中的IP地址),grep就无能为力了。
下一篇我们将学习三剑客的第二位——sed流编辑器,它能以非交互的方式对文本进行查找、替换、删除、插入操作。你将学会用一条命令批量修改上百个文件中的特定内容——这就是命令行效率的终极体现。
延伸思考: 如果你用的是grep -P,可以开启Perl兼容正则(PCRE),支持\d(数字)、\w(单词字符)、\s(空白)等快捷符号,以及环视断言(lookahead/lookbehind)。但要注意-P选项不是所有系统都有(macOS默认grep不支持),在编写需要跨平台运行的脚本时建议优先使用-E方式。
本回答由 AI 生成,内容仅供参考,请仔细甄别。
