🖥️ 第03章 · 文本查看与处理

cat head tail less grep sed awk cut sort uniq wc

文本查看与处理

这一章讲怎么"读"和"改"文本:查看文件内容、翻页、找关键词、按字段取列、排序去重、统计行数。日志分析、配置对比、数据清洗全靠这些救命的文本工具。

全文查看 cat 与分页 less

cat 适合短文件,一口气全输出;less 适合长文件,可以上下翻页。

cat /etc/os-release                  # 看系统发行版(很短)
cat -n nginx.conf                    # -n 显示行号
less /var/log/nginx/access.log       # 长日志用 less 翻页

less 里翻页与搜索:

按键 作用
空格 / PageUp PageDown 翻页
g / G 跳到开头 / 末尾
/关键词 向下搜索,n 下一个 N 上一个
q 退出

提示 长文件千万别用 cat,会刷屏几百行。判断标准:文件超过一屏就开 less。

看头尾 head / tail

head -5 access.log            # 前 5 行
tail -20 access.log           # 后 20 行
tail -f access.log            # 跟踪追加,实时滚动(看日志最爱)
tail -200 error.log > err.bak # 单独截出末尾 200 行

提示 tail -f 是最常用的"实时看日志"命令。在这台服务器上排查应用问题时,tail -f /var/log/nginx/access.log 配合刷新网页,能直观看到请求是否进来、状态码是多少。

head/tail 还能配合管道组合(第 8 章细讲),比如 ps aux | head -20。

找关键词 grep

grep 是文本世界里最重要的命令之一,按模式在文件里筛行。

选项 作用
-i 忽略大小写
-n 显示行号
-r 递归搜索目录
-v 反向查找,输出不匹配的行
-c 只统计匹配行数
-l 只输出包含匹配内容的文件名
grep -n "error" app.log              # 找所有含 error 的行+行号
grep -ri "listen" /etc/nginx/        # 递归找 nginx 配置里的 listen
grep -c "refused" error.log          # 数一数被拒绝的次数
grep -v "^#" /etc/nginx/nginx.conf   # 剔除注释行,看有效配置

在这台服务器上排查数据库连接失败:

grep -i "connection refused" /var/log/mysql/error.log

注意 grep 默认是"包含即匹配"的文本查找,不是精确匹配。要找关键词完整出现,用 \b 边界:grep -w "port"(仅匹配完整单词 port,不匹配 report)。

取字段 cut 与排序 sort、去重 uniq

先看一个典型场景——nginx 访问日志按 IP 统计访问量:

cut -d' ' -f1 access.log | sort | uniq -c | sort -rn | head -10

拆解每一步:

命令 作用
cut -d' ' -f1 以空格为分隔符,取第 1 列(即来源 IP)
sort 排序,把相同 IP 聚到一起
uniq -c 去重,并在前面加上每个值出现的次数
sort -rn 按次数数字倒序(最大的在前)
head -10 只看前十名

这就是"三件套"的经典用法:

命令 说明
cut -c1-5 文件 取每行第 1~5 字符
cut -d':' -f1 /etc/passwd 按 : 分隔取第 1 列为用户名
sort / sort -n / sort -r 默认字典序 / 按数字 / 倒序
uniq / uniq -c 去重 / 去重并计数(注意:必须先 sort)
wc -l 统计行数

提示 uniq 只能去掉相邻的重复行,所以必须先 sort。拿不准就永远"先 sort 后 uniq"。

统计这台服务器上登录过系统的用户数:

cut -d: -f1 /etc/passwd | sort | uniq | wc -l

统计 wc

wc -l access.log          # 行数
wc -c access.log          # 字节数
wc -w access.log          # 单词数

提示 脚本里判断"日志今天涨了多少条",用 wc -l 前后对比最直观。wc -c 常用于确认文件大小是否符合预期。

流编辑器 sed 与模式处理 awk

sed 适合逐行替换/删除,awk 适合按列做计算与格式化。

sed -i 's/old/new/g' file.conf     # 把文件里所有 old 替换成 new(-i 就地修改)
sed 's/:80/:8080/' nginx.conf      # 试替换,输出到屏幕,不改原文件
sed -n '10,20p' file               # 只打印第 10~20 行

别急着加 -i:先不加 -i 让结果打到屏幕上,确认替换正确后再加 -i 真正写回,避免把配置改坏。

awk '{print $1}' access.log          # 打印每行第 1 列
awk -F' ' '{print $1, $6}' log       # 指定分隔符,打印第 1、6 列
awk '$NF > 100 {print}' log          # 当最后一列数值大于 100 才打印
ps aux | awk '$3 > 5 {print $2}'     # 挑出 CPU 占用超 5% 的进程(PID)

注意 awk 默认以连续空白为分隔符,单引号里的 $1、$2 是 awk 的字段变量;千万不要和 shell 的 $1(脚本第一个参数)混淆。awk 里 $NF 表示"最后一列"。

综合实战:多工具协作

在这台服务器上给 nginx 日志做一个"Top 5 访问最频繁的客户端 IP":

cut -d' ' -f1 /var/log/nginx/access.log \
  | sort \
  | uniq -c \
  | sort -rn \
  | head -5

提示 反斜杠 \ 让一条长命令跨多行,易读不迷路。文本工具的精华就是"每个工具只做一件事,再用管道串起来"——这正是第 8 章的核心思想。

易错点

  • uniq 前必须 sort,否则去不干净。
  • sed -i 会直接改原文件,先试跑一遍看结果再写回。
  • grep 是文本子串匹配,要精确就加 -w 或 \b。
  • 看长文件别用 cat,会刷屏且难定位。

相关命令

cat、less、head、tail、grep、cut、sort、uniq、wc、sed、awk、tr(字符替换)、paste(按列合并)、diff(文件对比)。