前言

Linux 下一切皆文件,而日志、配置、命令输出全是文本。grep 找、sed 改、awk 算——这三把剑练熟,日常 80% 的文本处理需求都能搞定。

一、grep:文本搜索

# 基本搜索(支持管道)
grep "ERROR" app.log
journalctl -u nginx | grep -i "fail"        # -i 忽略大小写

# 常用选项
grep -n "root" /etc/passwd                   # 显示行号
grep -c "ERROR" app.log                      # 只统计匹配行数
grep -v "127.0.0.1" access.log              # 反向: 排除匹配的行
grep -r "bind 0.0.0.0" /etc/                 # 递归搜目录
grep -E "ERROR|FATAL" app.log                # 扩展正则, 多模式
grep -A 3 -B 1 "panic" app.log               # 显示匹配行的后3行、前1行
grep -w "error" app.log                      # 全词匹配

基础正则速查:

符号 含义 示例
^ 行首 grep "^#" 注释行
$ 行尾 grep ":$" 以冒号结尾
. 任意单字符 grep "r.ot"
* 前一字符 0+ 次 grep "go*gle"
[] 字符集合 grep "^[abc]"
[^] 取反 grep "^[^#]" 非注释行

实战:统计 Nginx 日志里出现最多的 10 个 IP:

awk '{print $1}' access.log | sort | uniq -c | sort -rn | head

二、sed:流编辑器

sed 逐行读取文本,对每行执行编辑命令后输出。核心场景是替换。

# 替换每行第一个匹配
sed 's/http/https/' conf.txt

# 替换所有匹配(全局 g 标志)
sed 's/http/https/g' conf.txt

# 直接修改文件(-i), 先备份为 .bak
sed -i.bak 's/8080/9090/g' app.conf

# 只处理第 2~5 行
sed '2,5s/8080/9090/g' app.conf

# 删除注释行和空行
sed -e '/^#/d' -e '/^$/d' sshd_config

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

# 在第 2 行后插入一行
sed '2a ServerName antidebug.cn' httpd.conf

# 打印 10~20 行(当 sed 用)
sed -n '10,20p' big.log

⚠️ 生产环境改配置前,先 sed 预览输出,确认无误后再加 -i;重要文件务必 -i.bak 留备份。

三、awk:文本计算器

awk 按**字段(列)**处理文本,默认以空格/Tab 分隔,$1 是第一列,$0 是整行。

# 打印第 1、3 列
awk '{print $1, $3}' data.txt

# 指定分隔符
awk -F: '{print $1, $7}' /etc/passwd

# 条件过滤: 磁盘使用率超过 80% 的分区
df -h | awk '$5+0 > 80 {print $6, $5}'

# 内置变量
awk -F: '{print NR": "$1}' /etc/passwd      # NR 当前行号
awk '{print NF}' file                       # NF 当前行字段数

# 使用分隔符美化输出
awk -F: -v OFS=' | ' '{print $1, $3, $7}' /etc/passwd

BEGIN / END 块做统计

# 统计第 1 列的总和与平均值
awk 'BEGIN {sum=0} {sum+=$1} END {print "sum="sum, "avg="sum/NR}' nums.txt

# 统计每种 HTTP 状态码出现次数
awk '{count[$9]++} END {for (s in count) print s, count[s]}' access.log

从日志里提取信息

# 提取 500 错误的 URI(第 9 列是状态码)
awk '$9 == 500 {print $7}' access.log | sort | uniq -c | sort -rn

# 提取响应时间超过 1s 的请求(假设 $NF 是耗时)
awk '$NF > 1.0 {print $4, $7, $NF}' access.log | head

四、三剑合璧:一条经典流水线

统计访问日志中 昨天 每小时 PV,并输出 Top 时段:

grep "$(date -d yesterday '+%d/%b/%Y')" access.log \
  | awk '{print substr($4,14,2)}' \
  | sort | uniq -c \
  | sort -rn | head -5

每一环的分工:

grep  → 框定目标行(按日期)
awk   → 抽取小时字段
sort  → 排序(uniq 统计前必须先排序)
uniq -c → 相邻去重并计数
sort -rn → 按数字倒序取 Top

五、速查表

需求 命令
找匹配行及上下文 grep -A3 -B1 "err" log
全局替换并备份 sed -i.bak 's/a/b/g' f
删除注释和空行 sed -e '/^#/d' -e '/^$/d' f
打印某列 awk '{print $3}' f
按条件过滤行 awk '$3 > 100' f
分组计数 awk '{c[$1]++} END{for(k in c) print k,c[k]}'
Top N sort | uniq -c | sort -rn | head

小结

三剑客的价值在于组合:管道把简单工具串成流水线,每一步只做一件事。日志分析、配置批量修改、数据提取统计,都离不开它们。建议把本文几个实战命令在自己的机器上敲一遍,肌肉记忆比收藏有用。


本文是「Linux 基础」系列第 3 篇,下篇预告:Linux 进程管理。