一、 前言

在Linux系统运维和日常开发工作中,高效处理文本数据是提升工作效率的关键。grep、sed、awk与find作为Linux文本处理“四剑客”,各自在特定场景下发挥着不可替代的作用。掌握这些工具不仅能简化重复性任务,还能实现复杂的文本分析和格式化输出。

学习路径建议:建议读者按照“基础语法→常用选项→实战案例→综合应用”的顺序逐步深入。首先熟悉每个工具的基本命令格式和核心参数,然后通过实际示例理解其工作原理,最后结合正则表达式等高级技巧解决真实场景中的问题。grep在之前的文章已经介绍过,本文将从sed开始,依次介绍printf、awk和find,帮助您构建系统的文本处理知识体系。

在Linux系统管理和日志处理中,grep、sed、printf、awk、find是不可或缺的文本处理利器。它们能够高效地完成文本的过滤、查找、替换、格式化与结构化分析,极大地提升了运维和开发的效率。本文将对sed、find、awk、printf四个工具进行系统介绍:sed(流编辑器)擅长基于行的文本替换与过滤;printf 用于精确控制输出格式,生成规整的报告;awk 则是一个强大的文本分析工具,尤其适合处理表格型数据并执行计算;find 是 Linux 系统中功能强大的文件查找工具,并支持对找到的文件执行各种操作。通过本文的学习,您将掌握它们的基本语法、核心功能及典型应用场景。

一、sed:流式文本编辑器

sed(Stream Editor)是一个非交互式的流编辑器。它逐行读取文本,根据预设规则对每行进行处理,并将结果输出到标准输出,默认不修改原始文件

1. 基本语法

sed [选项] '地址 命令' 文件名
  • 地址:指定要操作的行,可以是行号(如3)、范围(如2,5)或正则表达式(如/pattern/)。省略则作用于所有行。

2. 核心命令

① 替换(s)——最强大的功能
# 将每行第一个 "root" 替换为 "admin"
sed 's/root/admin/' /etc/passwd

# 全局替换:将所有 "nologin" 替换为 "disabled"
sed 's/nologin/disabled/g' /etc/passwd

# 忽略大小写替换
sed 's/error/warning/gi' app.log

# 给所有数字加上方括号(& 代表匹配到的整个内容)
echo "line 123 has number 456" | sed 's/[0-9][0-9]*/[&]/g'
# 输出:line [123] has number [456]

s 命令的语法是 s/原模式/替换内容/[标志]g 标志表示全局替换(每行所有匹配项),i 表示忽略大小写。

② 删除(d
# 删除第3行
sed '3d' file.txt

# 删除第2到第5行
sed '2,5d' file.txt

# 删除所有包含 "nologin" 的行
sed '/nologin/d' /etc/passwd

# 删除所有空行(含空格)
sed '/^[[:space:]]*$/d' file.txt
③ 打印(p)——配合 -n 使用
# 只打印第3行
sed -n '3p' file.txt

# 只打印包含 "root" 的行(效果类似 grep)
sed -n '/root/p' /etc/passwd

-n 选项会禁止 sed 的默认输出,只打印被 p 明确指定的行。

④ 插入与追加(ia
# 在第3行前面插入 "Hello"
sed '3i\Hello' file.txt

# 在第3行后面追加 "World"
sed '3a\World' file.txt

3. 高级技巧

分组替换(反向引用)

# 将日期从 YYYY-MM-DD 改为 DD/MM/YYYY,此处使用了后向引用,\3表示第三个小括号匹配的内容,\2、\1以此类推。
sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3\/\2\/\1/g' date.txt

利用正则表达式的分组功能(()),可以在替换时引用原文本的部分内容(\1\2…),常用于数据格式转换。

直接修改文件(-i

# 危险:直接修改且无备份
sed -i 's/old/new/g' file.txt

# 安全:先备份再修改
sed -i.bak 's/old/new/g' file.txt

-i.bak 会创建一个 .bak 后缀的备份文件,强烈建议养成这个习惯。

模式空间、保持空间与多行文本处理处理

空间 名称 本质 生命周期
Pattern Space(模式空间) 工作台(CPU缓存) 当前正在处理的那一行(或几行)内容 每轮循环清空重建
Hold Space(保持空间) 仓库(硬盘备份) 一个跨行循环持久保留的备用缓冲区 初始为空,除非你主动操作,否则数据一直保留

sed 的默认流程是:读一行 → 放入 Pattern Space → 执行命令 → 打印 Pattern Space → 清空 Pattern Space → 读下一行。而多行命令和保持空间命令,就是用来打破这个默认流程的。

多行文本处理命令速查表

命令 作用对象 详细说明
N Pattern Space 读取下一行追加到 Pattern Space(当前行 + \n + 下一行)
p Pattern Space 小写 p:打印整个 Pattern Space(不管有没有换行符)
P Pattern Space 大写 P:只打印 Pattern Space 中第一个 \n 之前的内容(即多行中的第一行)
d Pattern Space 小写 d:删除整个 Pattern Space,立即开始下一轮循环(读新行)
D Pattern Space 大写 D:删除 Pattern Space 中第一个 \n 之前的内容(即删掉第一行),若删后还有内容,不读新行,直接用剩余内容重启本轮循环
h → Hold Space 用 Pattern Space 的内容覆盖 Hold Space
H → Hold Space 将 Pattern Space 追加到 Hold Space(原内容 + \n + 新内容)
g Hold Space → 用 Hold Space 的内容覆盖 Pattern Space
G Hold Space → 将 Hold Space 追加到 Pattern Space(原内容 + \n + 保持空间内容)

多行文本处理举例

1、合并文件内容
文件内容如下:
admin
123456
user1
789123
user2
456789
audit
234567
需要将文件内容合并为如下形式
admin 123456
user1 789123
user2 456789
audit 234567
可以使用sed命令进行处理:sed ‘N; s/\n/ /g’ filename
在这里插入图片描述
三行合并为一行呢?可以使用如下方法进行合并:
文件内容:
admin
123456
/bin/bash
user1
789123
/bin/nologin
user2
456789
/bin/sh
audit
234567
/bin/disabled
合并命令:sed ‘N; N; s/\n/ /g; P; D;’ filename
在这里插入图片描述
文件所有内容合并为一行:
sed ‘:a; N; $!ba; s/\n//g;’ filename
在这里插入图片描述
所有行合并为一行有时会很有用,如你复制了一串秘钥,但是粘贴后由于格式问题变成了几行,这时可用该命令合并成一行。
2、反转文件内容
反转文件使用命令:sed ‘1!G; h; $!d’ filename
在这里插入图片描述


二、awk:文本分析与报表生成器

awk 并非简单的命令,而是一门专为文本处理设计的编程语言,诞生于贝尔实验室,名字取自三位创始人 Aho、Weinberger、Kernighan 的姓氏首字母。

1. 核心工作原理

awksed 最大的区别在于:sed 以“整行”为单位处理文本,而 awk 先将每行拆分为“字段”(默认用空格/制表符分隔),再按字段处理。

处理流程:逐行读取 → 字段拆分 → 条件匹配 → 执行操作

2. 基本语法

awk '[选项] '模式 { 动作 }' 文件名
  • -F:指定字段分隔符(如 -F: 表示用冒号分隔)
  • $1, $2, $3...:引用第1、2、3个字段,$0 代表整行
  • NR:当前行号
  • NF:当前行的字段数量

3. 三大核心模块

awk 的脚本结构由三个可选模块组成:

模块 执行时机 作用
BEGIN 读取文本前执行(仅1次) 初始化变量、打印表头
主体 逐行读取时执行(每行触发) 字段提取、条件判断
END 读取文本后执行(仅1次) 汇总统计、打印最终结果

4. 实战案例

① 打印指定字段

# 打印 /etc/passwd 的第一列(用户名)
awk -F: '{print $1}' /etc/passwd

# 打印第1和第3列
awk -F: '{print $1, $3}' /etc/passwd

② 条件筛选

# 打印 UID 大于 1000 的用户名
awk -F: '$3 > 1000 {print $1}' /etc/passwd

# 打印包含 "root" 的行
awk '/root/ {print $0}' /etc/passwd

③ 统计与计算

# 统计文件行数
awk 'END {print NR}' file.txt

# 计算某列的总和
awk 'BEGIN {sum=0} {sum += $3} END {print "Total:", sum}' data.txt

④ BEGIN/END 实战:生成报表

awk -F':' 'BEGIN {print "===== 用户列表 =====\n用户名\tUID"}
     {print $1 "\t" $3}
     END {print "===== 共 " NR " 个用户 ====="}' /etc/passwd

在这里插入图片描述


三、printf:格式化输出专家

printf 命令用于格式化输出,它比 echo 更强大、更精确,是编写可移植 Shell 脚本的首选工具。

1. 基本语法

printf "格式化字符串" [变量或值]

注意printf 默认不会像 echo 那样自动添加换行符,需要手动加上 \n

2. 常用格式符

格式符 说明
%s 字符串
%d 十进制整数
%f 浮点数
%x 十六进制整数
%o 八进制整数
%% 输出百分号本身

3. 实战案例

① 基本输出

printf "Hello, World!\n"
# 输出:Hello, World!

printf "我有 %d 个苹果,每个价格 %.2f 元。\n" 5 3.14
# 输出:我有 5 个苹果,每个价格 3.14 元。

② 对齐与宽度控制

# 左对齐(-)、指定宽度(10)
printf "%-10s %-8s %s\n" "姓名" "年龄" "城市"
printf "%-10s %-8d %s\n" "张三" 25 "北京"
printf "%-10s %-8d %s\n" "李四" 30 "上海"

输出:

姓名       年龄     城市
张三       25       北京
李四       30       上海

③ 与 awk 配合使用

# 用 awk 提取数据,用 printf 格式化输出
awk -F: '{printf "%-20s %-5s\n", $1, $3}' /etc/passwd | head -5

④ 输出到变量(-v

# 将格式化结果存入变量
printf -v mydate "%s" "$(date +%Y-%m-%d)"
echo "Today is $mydate"

四、find:文件搜索之王

find 是 Linux 下最强大的文件搜索工具,支持按文件名、类型、大小、时间、权限、所有者等多维度组合条件搜索。

1. 基本语法

find [路径] [选项] [表达式]

2. 常用搜索条件

① 按文件名

# 查找所有 .txt 文件(区分大小写)
find /home -name "*.txt"

# 查找 .txt 文件(不区分大小写)
find /home -iname "*.TXT"

② 按文件类型

# 查找普通文件
find /var/log -type f -name "*.log"

# 查找目录
find /etc -type d -name "*conf*"

# 查找符号链接
find /usr/bin -type l

③ 按时间

Linux 中每个文件有三个时间戳:atime(访问时间)、mtime(修改时间)、ctime(状态改变时间)。

# 查找 7 天内修改过的文件(- 表示"不到")
find /var/log -mtime -7

# 查找 7 天前修改的文件(+ 表示"超过")
find /var/log -mtime +7

# 查找 1 小时内访问的文件
find /var -amin -60

④ 按文件大小

# 查找大于 100MB 的文件
find /var -size +100M

# 查找小于 1KB 的文件
find /tmp -size -1k

# 查找空文件
find /tmp -size 0

3. 组合条件搜索

find 支持逻辑运算符:-a(与)、-o(或)、!(非)。

# 查找大于 1MB 且最近 30 天内修改过的 .txt 文件
find /path -name "*.txt" -size +1M -mtime -30

# 查找 /var/log 下 7 天内修改且权限为 644 的日志文件
find /var/log -type f -mtime -7 -perm 644 -name "*.log"

# 查找普通文件或符号链接
find . -type f -o -type l

4. 对搜索结果执行操作(-exec

# 查找所有 .sh 文件并搜索其中包含 "keyword" 的行
find . -type f -name "*.sh" -exec grep -Hn "keyword" {} +

# 批量删除所有 .tmp 文件
find /tmp -name "*.tmp" -delete

# 将 .log 文件移动到备份目录
find . -type f -name "*.log" -exec mv {} /backup/logs/ \;

小技巧-exec {} +-exec {} \; 效率更高,因为 + 会批量传递文件,减少命令调用次数。

5. 限制搜索深度

# 仅在当前目录搜索(不进入子目录)
find . -maxdepth 1 -type f -name "*.txt"

五、四大利器协同作战

这四个工具单独使用已经很强大了,但真正的威力在于组合使用。通过管道(|)将它们串联起来,可以实现“1+1+1+1 > 4”的效果。

案例一:查找大文件并格式化输出

# 查找 /var 下大于 100MB 的文件,格式化显示大小和路径
find /var -type f -size +100M -exec ls -lh {} \; | \
    awk '{printf "%-10s %s\n", $5, $9}'

在这里插入图片描述

案例二:批量修改配置文件

# 查找所有 .conf 文件,将 "old_host" 替换为 "new_host"
find /etc -type f -name "*.conf" -exec sed -i.bak 's/old_host/new_host/g' {} \;

案例三:日志分析报表

# 从 access.log 中提取状态码并统计
awk '{print $9}' access.log | sort | uniq -c | sort -rn | \
    printf "%-10s %s\n" "次数" "状态码"
    awk '{printf "%-10d %s\n", $1, $2}'

案例四:查找并清理旧日志

# 查找 30 天前修改的 .log 文件,压缩归档
find /var/log -type f -name "*.log" -mtime +30 -exec gzip {} \;

案例五:统计访问nginx次数前两名的ip地址

awk -F' ' '{print $1}' /var/log/nginx/access.log |sort -nr |uniq -c |sort -nr -k 1 |head -2 |awk 'BEGIN{printf "%-10s %-10s\n","访问次数","ip地址"}{printf "%-15s %-10s\n",$1,$2}'

在这里插入图片描述


六、快速对照表

工具 定位 核心能力 典型场景
sed 流编辑器 按行替换、删除、插入 批量修改配置文件
awk 文本分析语言 按字段处理、统计、报表 日志分析、数据提取
printf 格式化输出 精确控制输出格式 脚本中生成格式化报告
find 文件搜索 多条件查找文件 定位文件、批量操作

七、避坑指南

  1. sed 忘记 -i:不加 -i 所有修改只是预览,原文件不变。
  2. sed 正则转义:默认使用基础正则,+?{} 需要转义。建议加 -E 使用扩展正则。
  3. awk 字段索引从 1 开始$0 是整行,$1 是第一列,没有 $0 作为第一列的说法。
  4. find 的时间符号- 表示“不到”,+ 表示“超过”(如 -mtime -7 是 7 天内,-mtime +7 是 7 天前)。
  5. printf 不自动换行:记得加 \n

掌握这四个工具,你就能在日常的日志排查、配置修改、数据统计、文件管理中游刃有余。它们不是孤立的工具,而是一套可以灵活组合的文本处理武器库。从今天开始,试着在实际工作中多用管道将它们串联起来,你会发现效率的提升远超想象。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐