Shell 文本处理核心:正则表达式 + 三剑客(grep、sed、awk)全解析
在 Linux 系统运维和 Shell 脚本开发中,文本处理是高频核心需求,而正则表达式是文本匹配的通用规则,grep、sed、awk(文本处理三剑客)则是落地正则规则、完成过滤 / 编辑 / 分析的实用工具。
一、正则表达式:文本匹配的 “通用规则语言”
正则表达式是描述文本模式的专用语言,它不匹配固定字符串,而是通过一系列符号定义匹配规则,匹配符合规则的任意字符串。它是 grep、sed、awk 的核心能力基础,学会正则,才能灵活使用三剑客,而非死记硬背命令。
1. 正则表达式的分类
Shell 中常用两类正则,核心区别是部分符号是否需要转义,工具可通过指定选项切换:
- 基本正则表达式(BRE):默认支持,
+、?、()等符号需加反斜杠\转义; - 扩展正则表达式(ERE):语法更简洁,符号无需转义,需通过
grep -E、sed -E启用。
2. 基本正则表达式(BRE)核心语法
(1)字符匹配:匹配单个字符
| 语法 | 作用 | 示例 |
|---|---|---|
. | 匹配任意单个字符(除换行符) | a.c 匹配 abc、a1c、a#c 等 |
[] | 匹配括号内任意一个字符 | [abc] 仅匹配 a、b、c 其一 |
[^] | 匹配不在括号内的任意一个字符 | [^0-9] 匹配非数字字符 |
[a-z] | 匹配指定范围字符,支持字母 / 数字 | [0-9a-z] 匹配数字和小写字母 |
\w | 匹配字母、数字、下划线(等价于 [0-9a-zA-Z_]) | \w+ 匹配连续的单词字符 |
(2)位置锚定:匹配字符的位置(无实际字符,仅定位)
| 语法 | 作用 | 示例 |
|---|---|---|
^ | 行首锚定:匹配行的开头位置 | ^error 匹配以 error 开头的行 |
$ | 行尾锚定:匹配行的结尾位置 | warn$ 匹配以 warn 结尾的行 |
^$ | 组合使用,匹配空行(行首到行尾无任何字符) | grep -n ^$ file.txt 查找空行号 |
\b | 词边界锚定:匹配独立单词的边界 | \bthe\b 仅匹配独立的 the,避免匹配 there、other |
(3)次数匹配:指定前一个字符的出现次数
| 语法 | 作用 | 示例 |
|---|---|---|
* | 前一个字符出现0 次或多次(匹配任意次数) | ab*c 匹配 ac、abc、abbc 等 |
\++ | 前一个字符出现1 次或多次(BRE 需转义,ERE 直接用 +) | a\++b 匹配 ab、aab、aaab 等 |
\? | 前一个字符出现0 次或 1 次(可选字符) | ab\?c 仅匹配 ac、abc |
\{n\} | 前一个字符恰好出现 n 次 | a\{3\} 仅匹配 aaa |
\{n,\} | 前一个字符至少出现 n 次 | a\{2,\} 匹配 aa、aaa、aaaa 等 |
\{n,m\} | 前一个字符出现n 到 m 次(闭区间) |
|
(4)符号组
| 符号 | 含义与用法 | 示例 |
| () (小括号) | 1. 分组:将多个字符视为一个整体,作为匹配单元 2. 分支匹配:用 |表示 “或” 关系 |
- (ab)+ 匹配 ab、abab、ababab 等 - `(ab)匹配a或b` |
| [] (中括号) | 1. 匹配「括号内任意单个字符」 2. 支持范围:[0-9](数字)、[a-z](小写字母) 3. 支持取反:[^0-9](非数字) 4. 特殊字符无需转义:[.*+] 直接匹配 .、*、+ |
- - |
| {} (大括号) | 限定重复次数(需开启扩展正则 -E): - {n}:恰好匹配 n 次 - {n,}:至少匹配 n 次 - {n,m}:匹配 n 到 m 次 |
- - |
| \ (转义符) | 1. 转义元字符:将有特殊含义的元字符(如 . * +)变回普通字符 2. 赋予普通字符特殊含义(仅正则):将普通字符转为特殊匹配序列 | 1. 转义元字符: - \* 匹配普通星号 * - grep '\*' test.txt 匹配所有含 * 的行 2. 赋予特殊含义: - \d 匹配任意数字(等价于 [0-9]) |
(5)引号组
| 引号类型 | 核心特性 | 变量 / 命令解析 | 转义规则 | 典型用途 |
| '' 单引号 | 强引用(纯字符串) | ❌ 不解析变量($)、命令(`)、转义符(\) | 仅 '' 本身无法直接包含(需特殊处理) | 固定字符串、避免任何解析 |
"" 双引号 | 弱引用(解析型字符串) | ✅ 解析变量($)、命令(`);❌ 不解析通配符(*?) | 仅 \$/ \``/ " /\` 可转义 | 包含变量 / 命令的字符串 |
` 反引号 | 命令替换(非引号) | ✅ 执行包裹的命令,返回输出结果 | 遵循 Shell 转义规则 | 嵌入命令执行结果(等价于 $()) |
总结:
1.双引号对 $/` 的处理:识别→执行→替换结果;
2. 单引号对 $/` 的处理:仅作为普通字符,不执行;
3. 记忆技巧:双引号是 “智能解析”,单引号是 “原样输出”,而 ` 本身是 “命令执行器”,在双引号内会正常工作。
3. 扩展正则表达式(ERE):简化版 BRE
使用 grep -E、egrep、sed -E 启用,无需对特殊符号转义,语法更直观,推荐优先使用,核心简化点:
+替代\+:a+b匹配 a 出现 1 次及以上?替代\?:ab?c匹配 b 出现 0 次或 1 次()替代\(\):(ab)*匹配 ab 整体出现 0 次及以上|表示或:error|warn匹配 error 或 warn(BRE 无此语法)
示例:grep -E 'error|warn' file.log 匹配文件中含 error 或 warn 的行。
二、grep:正则匹配的 “文本过滤利器”
grep 是Global Regular Expression Print的缩写,核心作用是按正则规则从文本中匹配并输出符合条件的行,是文本过滤的首选工具,也是正则表达式最基础的应用载体。
1. 核心语法
bash
运行
grep [选项] '正则表达式/匹配字符串' 目标文件/目录
2. 常用核心选项(按使用频率排序)
| 选项 | 作用 | 实用示例 | ||
|---|---|---|---|---|
-i | 忽略大小写匹配 | grep -i 'Error' file.log | ||
-v | 反向匹配:输出不包含匹配内容的行 | grep -v 'debug' app.log(过滤调试日志) | ||
-n | 显示匹配行的行号(排错必备) | grep -n '^error' file.log | ||
-c | 只统计匹配到的行数,不输出具体内容 | grep -c 'success' access.log(统计成功请求数) | ||
-E | 启用扩展正则(等价于 egrep) | `grep -E 'error | warn | info' system.log` |
-o | 只输出匹配到的部分,而非整行 | grep -o '\b[0-9]\+\b' file.txt(仅提取数字) | ||
-r | 递归搜索目录下所有文件 | grep -r 'TODO' /project/code(搜索项目中待办注释) | ||
-A/B/C n | 显示匹配行及后 / 前 / 前后n 行(上下文查看) | grep -C 2 'ERROR' file.log(显示错误行前后 2 行) | ||
-q | 静默模式:不输出结果,仅返回状态码 | if grep -q 'error' file.log; then echo "存在错误"; fi(脚本判断) |
3. 正则与 grep 的配合示例
bash
运行
# 1. 基础正则:匹配以root开头的行,显示行号
grep -n '^root' /etc/passwd
# 2. 扩展正则:匹配含error或warn的行,忽略大小写
grep -Ei 'error|warn' /var/log/nginx/error.log
# 3. 反向匹配:过滤空行和以#开头的注释行
grep -v '^$|^#' /etc/nginx/nginx.conf
三、sed:正则驱动的 “流文本编辑大师”
sed 是Stream Editor的缩写,以行为单位处理文本,支持替换、删除、插入、打印等编辑操作,核心优势是批量修改文本,同样依托正则表达式实现精准匹配行 / 内容。
1. 核心语法
bash
运行
sed [选项] '地址定位 编辑命令' 目标文件
- 地址定位:按行号 / 正则规则选择要处理的行(可选,不写则处理所有行);
- 编辑命令:对选中的行执行的操作(替换、删除、打印等);
- 正则规则:地址定位和替换操作中,均可使用正则表达式。
2. 常用选项
| 选项 | 作用 | 关键说明 |
|---|---|---|
-i | 直接修改原文件 | 建议先不加 - i 测试,确认结果后再添加(避免误改) |
-E | 启用扩展正则 | 替换 / 定位时无需转义特殊符号 |
-n | 静默模式:仅输出被处理的行 | 常与打印命令p配合,避免重复输出 |
-e | 执行多个编辑命令 | 按顺序执行,实现多步修改 |
3. 核心用法:地址定位 + 编辑命令
(1)地址定位(选行):支持行号 / 正则
| 定位语法 | 作用 | 示例 |
|---|---|---|
n | 第 n 行 | sed '3d' file.txt(删除第 3 行) |
n,m | 第 n 到 m 行 | sed '1,5p' -n file.txt(打印 1-5 行) |
$ | 最后一行 | sed '$s/old/new/' file.txt(替换最后一行的 old 为 new) |
/正则/ | 匹配正则规则的行 | sed '/^error/d' file.log(删除以 error 开头的行) |
(2)常用编辑命令(核心:s 替换 /d 删除 /p 打印)
| 命令 | 作用 | 语法 / 示例 | |
|---|---|---|---|
s | 替换文本(最常用) | 语法:s/旧内容/新内容/标志;示例:`sed -E's/error | warn/INFO/g' file.log` |
d | 删除匹配行 | sed '/^#/d' file.conf(删除注释行) | |
p | 打印匹配行 | sed -n '/success/p' file.log(仅打印含 success 的行) |
(3)替换命令的关键标志
g:全局替换(行内所有匹配项,默认只替换第一个);i:忽略大小写匹配;p:输出替换后的行(需配合-n)。
4. 正则与 sed 的核心实战
bash
运行
# 1. 批量替换:将文件中所有old替换为new,直接修改原文件(扩展正则)
sed -i -E 's/old/new/g' data.txt
# 2. 过滤+替换:先删除空行,再将error替换为ERROR(多命令执行)
sed -e '/^$/d' -e 's/error/ERROR/g' file.log
# 3. 正则匹配替换:提取手机号,将11位数字替换为星号隐藏
echo "手机号:13812345678" | sed -E 's/([0-9]{3})([0-9]{4})([0-9]{4})/\1****\3/'
四、awk:正则赋能的 “结构化文本分析引擎”
awk 不仅是工具,更是一门轻量的编程语言,以字段(列)为单位处理文本,擅长结构化文本(日志、CSV、/etc/passwd)的统计、计算、格式化输出,正则表达式在 awk 中可用于行匹配和字段处理,灵活性最高。
1. 核心概念(理解 awk 的关键)
awk 将文本按行和列拆解,核心术语:
- 记录:默认以换行符分隔,每一行是一条记录;
- 字段:默认以空白符(空格 / 制表符)分隔,每一列是一个字段;
- 用
$1、$2、$3... 表示第 1、2、3 列,$0表示整行; - 最后一列可用
$NF表示(NF 是内置变量,代表当前行字段总数);
- 用
- 内置变量:awk 自带的实用变量,无需定义直接用
变量 作用 NF当前行的字段总数 NR当前处理的行号(全局) FS字段分隔符(默认空白,可用 -F指定)OFS输出字段分隔符(默认空白)
2. 核心语法
bash
运行
awk [选项] 'pattern { action }' 目标文件
pattern:匹配条件(行号 / 正则表达式),满足条件的行才执行 action;action:处理动作(打印、计算、判断等),默认动作是print(输出整行);- 正则规则:
pattern部分可直接写正则,用/正则/表示。
3. 常用选项
| 选项 | 作用 | 示例 | |
|---|---|---|---|
-F | 指定字段分隔符(支持正则) | awk -F: '{print $1}' /etc/passwd(以:分隔,提取用户名) | |
-v | 定义自定义变量 | awk -v num=10 '{print $1+num}' file.txt(字段 1 加 10 输出) | |
-E | 启用扩展正则 | `awk -E '/error | warn/{print $0}' file.log` |
4. 正则与 awk 的核心应用场景
(1)正则行匹配:过滤符合规则的行,提取字段
bash
运行
# 1. 以:分隔,提取/etc/passwd中UID大于1000的用户名和UID
awk -F: '$3>1000 {print "用户名:"$1, "UID:"$3}' /etc/passwd
# 2. 正则匹配:从Nginx日志中提取含/API/的请求行,输出IP和请求路径
awk '/\/API\// {print $1, $7}' /var/log/nginx/access.log
(2)正则字段处理:对指定字段做正则匹配 / 替换
awk 内置match()、gsub()函数,支持对字段执行正则操作:
bash
运行
# 将第2列中的所有数字替换为*,并输出整行
awk '{gsub(/[0-9]/, "*", $2); print $0}' file.txt
(3)经典实战:正则过滤 + 统计计算
bash
运行
# 统计Nginx访问日志中,每个IP的访问次数(按次数降序)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# 提取成绩表中,数学分数>85的学生姓名和分数(跳过标题行,正则匹配行)
awk -F, 'NR>1 && $3>85 {print "姓名:"$1, "数学:"$3}' score.csv
五、文本处理辅助工具:sort/uniq/wc(与三剑客配合)
实际工作中,三剑客常与sort(排序)、uniq(去重)、wc(统计)配合,完成过滤→排序→去重→统计的完整流程,这三个工具轻量且高效,是文本处理的 “黄金搭档”。
1. sort:对文本行排序
bash
运行
sort [选项] 目标文件
-n:按数值大小排序(默认按 ASCII 码排序,数字会排错);-r:降序排列(默认升序);-k:指定排序字段(如-k2按第 2 列排序);-t:指定字段分隔符(与 awk-F一致)。
2. uniq:去除相邻重复行
关键:仅处理相邻重复行,需先
sort排序再去重,否则无效!
bash
运行
uniq [选项] 目标文件
-c:统计每行出现的次数(最常用);-i:忽略大小写去重。
3. wc:统计行数 / 单词数 / 字节数
bash
运行
wc [选项] 目标文件
-l:只统计行数(文本处理最常用);-w:只统计单词数;-c:只统计字节数。
4. 组合实战:三剑客 + 辅助工具分析日志
bash
运行
# 实战:统计Nginx访问日志中,访问量最高的前5个IP(完整流程)
awk '{print $1}' /var/log/nginx/access.log # 提取所有IP
| sort # 对IP排序,让重复IP相邻
| uniq -c # 去重并统计每个IP的访问次数
| sort -rn # 按访问次数降序排序
| head -5 # 取前5个IP
六、学习总结:正则与三剑客的核心适用场景
按先正则、后工具的逻辑学习后,可清晰区分三剑客的定位,避免混用,核心总结:
- 正则表达式:所有工具的基础,先明确 “要匹配什么”,再选工具;
- grep:纯文本过滤,快速找符合规则的行,轻量高效,首选;
- sed:行级文本编辑,批量替换 / 删除 / 插入文本,适合修改文件内容;
- awk:字段级文本分析,擅长结构化文本的提取、统计、计算,功能最强;
- 辅助工具:sort/uniq/wc 与三剑客配合,完成排序、去重、统计的收尾工作。
核心原则:过滤用 grep,修改用 sed,分析用 awk。
更多推荐
所有评论(0)