易君召
易君召
发布于 2026-07-29 / 0 阅读
0
0

Linux正则表达式三剑客grep /sed/awk 完整深度分析

一、三者核心定位与底层联系

1. 底层同源联系

三者都起源于 Unix 文本处理生态,均支持正则表达式,是 Linux 三剑客,配合管道 | 流水线处理文本:

shell

cat file.txt | grep 过滤 | sed 行替换/修改 | awk 格式化计算输出
  • 共同输入:文件、管道标准输入 (stdin)

  • 共同能力:基础正则、匹配行筛选、批量文本处理

  • 协同逻辑:grep 捞行 → sed 修改行内容 → awk 拆分字段、运算、格式化

2. 核心本质区别(一句话总结)

工具

核心职能

处理粒度

设计初衷

grep

行过滤、匹配查找

整行

只筛选符合正则的行,不修改、不拆分列、不计算

sed

流编辑器、行级文本替换 / 增删

整行、行内字符

批量修改文本,支持增删改行、字符替换,弱字段处理、无数学运算

awk

文本语言、列 / 字段处理、计算

字段 (列)、记录 (行)、变量运算

小型编程语言,自动按分隔符拆分行成多列,支持循环、判断、数学运算、格式化输出

二、详细对比:联系 vs 核心差异

1. 相同点(联系)

  1. 全部支持 POSIX 正则表达式,支持 ^ $ . * + ? () [] 等元字符

  2. 支持读取文件,支持管道接收上游输出,适合流水线组合使用

  3. 默认按为基础处理单元,一次读取一行处理

  4. 支持参数自定义匹配规则,支持批量处理多文件

2. 关键差异(维度拆解)

(1)处理目标差异

  • grep:只做筛选,保留匹配行,删除不匹配行;只读不写(除非配合重定向)

  • sed:修改文本,替换字符、删除行、插入行、追加内容,流式修改

  • awk:结构化解析,自动分割行成多列($1 $2 ... $NF),支持数值计算、逻辑判断、格式化打印

(2)编程能力差距(最重要区分点)

  1. grep:无编程能力,没有变量、循环、if 判断、数学计算,只有匹配 / 不匹配两种逻辑

  2. sed:极简行编辑指令,只有简单寻址 + 操作(s 替换 /d 删 /a 增 /i 插),无复杂逻辑,不能做加减乘除运算

  3. awk:完整小型编程语言

    • 内置变量:$0整行、$1第一列、NF列总数、NR行号、FS分隔符、OFS输出分隔符

    • 语法:if/else 判断、for/while 循环、数组、四则运算、字符串拼接、格式化输出 printf

(3)适用数据格式差异

  • grep:无结构化要求,纯无序日志、乱文本均可,只关心整行是否匹配关键词

  • sed:适合无结构纯文本,侧重全局字符替换(比如替换日志里的 IP、脱敏手机号)

  • awk:高度适配结构化文本(CSV、日志、表格、空格分隔数据,如 nginx 访问日志、df 磁盘输出、ps 进程列表)

三、三者独立适用场景

1. grep 专属场景(查找筛选,只捞不取)

  1. 日志检索:过滤包含报错、关键词的日志行

  2. 代码检索:项目目录批量查找包含指定函数 / 变量的文件

  3. 过滤命令输出:过滤 ps 进程、docker 容器、端口占用

  4. 简单正则匹配:匹配手机号、IP、邮箱等格式行

不适合:文本替换、列提取、数值计算、格式化输出

2. sed 专属场景(批量修改文本,流替换)

  1. 文件全局字符替换:批量替换 IP、域名、敏感信息脱敏

  2. 行操作:删除空行、删除注释行、指定行插入 / 追加内容

  3. 流式预处理:上游输出文本临时替换,再交给 awk 处理

  4. 批量修改配置文件:注释 / 取消注释配置参数

不适合:多列拆分、数值统计、复杂逻辑判断、报表格式化

3. awk 专属场景(结构化文本分析、统计、格式化输出)

  1. 日志分析:nginx/Java 日志提取状态码、请求耗时、IP,统计访问量

  2. 系统监控数据统计:df 磁盘使用率、free 内存、CPU 使用率求和 / 求平均

  3. 表格数据处理:CSV、空格分隔文件提取指定列、过滤列数值

  4. 数据运算:求和、平均值、最大值、分组统计(类似 SQL 分组)

  5. 自定义格式化输出:对齐表格、拼接自定义字符串

不适合:单纯关键词过滤(grep 更简洁)、全局简单字符替换(sed 更简洁)

四、完整实战范例 + Demo(可直接复制运行)

前置测试文件 demo.txt

先创建测试文本,所有示例共用:

shell

cat > demo.txt << EOF
100 root /usr/bin/bash 127.0.0.1
201 mysql /usr/sbin/nologin 192.168.1.10
305 nginx /usr/sbin/nologin 192.168.1.20
400 redis /usr/bin/bash 127.0.0.2
502 www /usr/sbin/nologin 192.168.1.30
EOF

文本结构:编号 用户名 shell 客户端IP


第一部分:grep 常用范例

基础语法

shell

grep [参数] "正则/关键词" 文件名
# 管道用法
cat demo.txt | grep "关键词"

高频参数

  • -i:忽略大小写

  • -v:反向匹配(输出不匹配的行)

  • -n:输出匹配行的行号

  • -c:统计匹配行数

  • -r/-R:递归遍历目录所有文件

  • -o:只输出匹配到的字符串,不输出整行

Demo 示例

  1. 匹配包含 192.168 的内网 IP 行

shell

grep "192.168" demo.txt
  1. 反向过滤:排除 nologin 用户(只输出 bash 登录用户)

shell

grep -v "nologin" demo.txt
  1. 忽略大小写匹配 nginx,同时显示行号

shell

grep -in "nginx" demo.txt
  1. 统计内网 IP 一共有多少行

shell

grep -c "192.168" demo.txt
  1. 只提取所有 IP 字符串(-o 只输出匹配内容)

shell

grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" demo.txt
  1. 递归查找 /var/log 目录下包含 error 的日志

shell

grep -r "error" /var/log

第二部分:sed 常用范例(流编辑器)

基础语法

shell

sed [参数] '寻址+操作指令' 文件
# 管道用法
cat demo.txt | sed '指令'
# -i 直接修改原文件(高危,测试不加-i)
sed -i 's/原内容/新内容/g' demo.txt

核心指令

  • s/A/B/g 替换:把 A 全局替换为 B,g = 全局,不加只替换每行第一个匹配

  • d 删除匹配行

  • a 匹配行下方追加文本

  • i 匹配行上方插入文本

高频参数

  • -n:只输出匹配修改后的行(默认输出全部行)

  • -i.bak:修改原文件并自动生成备份文件(安全写法)

Demo 示例

  1. 全局替换:把所有 192.168 替换为 10.0.0

shell

sed 's/192.168/10.0.0/g' demo.txt
  1. 删除包含 nologin 的行

shell

sed '/nologin/d' demo.txt
  1. 删除空行(常用日志清理)

shell

sed '/^$/d' demo.txt
  1. 在 nginx 用户行下方追加注释文本

shell

sed '/nginx/a # nginx web服务用户' demo.txt
  1. 只输出修改后的行(搭配 - n 参数)

shell

sed -n 's/bash/登录shell/p' demo.txt
  1. 安全修改原文件,自动备份 demo.txt.bak

shell

sed -i.bak 's/usr\/sbin\/nologin/禁止登录/g' demo.txt

第三部分:awk 常用范例(最强结构化处理)

基础语法

shell

awk '条件{执行操作}' 文件
# 内置核心变量
$0 = 整行文本
$1 = 第一列,$2第二列...$NF最后一列
NF = 当前行总列数
NR = 当前行号
FS = 输入分隔符(默认空格)
OFS = 输出分隔符(默认空格)

Demo 示例(基于 demo.txt)

  1. 提取第 2 列(所有用户名)

shell

awk '{print $2}' demo.txt
  1. 多列输出:打印行号、用户名、IP,自定义分隔符|

shell

awk '{print NR "|" $2 "|" $4}' demo.txt
  1. 条件过滤:只输出编号大于 300 的行(数值运算)

shell

awk '$1 > 300 {print $0}' demo.txt
  1. 匹配字符串条件:只输出 IP 为 127 开头的本地用户

shell

awk '$4 ~ /^127/ {print $2 " 本地用户"}' demo.txt
  1. 反向匹配:过滤非 nologin 用户,求和第一列所有编号

shell

awk '$3 !~ /nologin/ {sum += $1} END{print "总编号和:", sum}' demo.txt
  1. 修改输出分隔符,格式化表格输出

shell

awk 'BEGIN{OFS="\t"} {print $1,$2,$4}' demo.txt
  1. 日志经典场景:统计 nginx 日志 200、404 状态码数量

shell

# 模拟nginx日志演示
cat > nginx.log <<EOF
127.0.0.1 - - [29/Jul/2026] "GET /index" 200
192.168.1.10 - - [29/Jul/2026] "POST /api" 404
127.0.0.1 - - [29/Jul/2026] "GET /list" 200
EOF
# awk统计状态码
awk '{code=$9; count[code]++} END{for(i in count) print "状态码",i,"访问次数",count[i]}' nginx.log

第四部分:三剑客联合流水线实战(综合 Demo)

需求:从 demo.txt 中筛选内网 IP 用户,把 nologin 替换为禁止登录,最终输出用户名、IP、编号大于 200 的数据

shell

cat demo.txt \
| grep "192.168" \          # 1.grep过滤内网IP行
| sed 's/nologin/禁止登录/g' \ # 2.sed替换登录字段
| awk '$1 > 200 {print "用户:"$2,"IP:"$4}' # 3.awk过滤数值并格式化输出

五、工具选型速查表(快速判断用哪个)

  1. 只找匹配行、检索关键词 → grep

  2. 需要批量替换字符、增删整行、修改文本内容 → sed

  3. 需要拆分多列、提取指定字段、数值计算、分组统计、格式化报表 → awk

  4. 复杂流水线:grep 筛选 → sed 预处理替换 → awk 统计输出

六、补充总结

  1. grep 是筛选器:只过滤,不修改、不计算;简单检索首选。

  2. sed 是替换工具:面向整行字符修改,擅长全局批量替换,无复杂运算。

  3. awk 是文本编程语言:结构化数据处理王者,支持变量、判断、循环、统计,日志分析、报表输出必备。

  4. 三者不是替代关系,而是互补流水线工具,企业运维、日志分析、文本处理场景通常组合使用。


评论