🔍 grep
Global Regular Expression Print
按模式过滤行,擅长搜索和过滤文本
✂️ sed
Stream Editor
流式编辑,擅长替换、删除、插入行内容
📊 awk
Aho Weinberger Kernighan
字段分析,擅长结构化数据提取和计算
1️⃣ 正则表达式基础
| 符号 | 含义 | 示例 |
|---|---|---|
. | 匹配任意单个字符(换行除外) | a.c → abc/a1c |
* | 前面字符出现0次或多次 | ab*c → ac/abc/abbc |
+ | 前面字符出现1次或多次(ERE) | ab+c → abc/abbc |
? | 前面字符出现0或1次(ERE) | ab?c → ac/abc |
^ | 行首 | ^error → error开头的行 |
$ | 行尾 | error$ → error结尾的行 |
[] | 字符集合 | [aeiou] → 任意小写元音 |
[^] | 排除字符集合 | [^0-9] → 非数字 |
\b | 单词边界 | \bword\b |
{n,m} | 出现n到m次(ERE) | [0-9]{1,3} |
2️⃣ grep — 文本过滤利器
# 基本用法 grep "error" /var/log/syslog # 过滤含 error 的行 grep -i "error" /var/log/syslog # 不区分大小写 grep -n "error" /var/log/syslog # 显示行号 grep -v "error" /var/log/syslog # 反向:不包含 error 的行 grep -c "error" /var/log/syslog # 统计匹配行数 grep -l "error" /var/log/*.log # 只显示匹配的文件名 grep -r "error" /var/log/ # 递归搜索目录 grep -A3 "error" /var/log/syslog # 显示匹配行及后3行 grep -B3 "error" /var/log/syslog # 显示匹配行及前3行 grep -C3 "error" /var/log/syslog # 显示匹配行及前后3行 bash
# -E 扩展正则(ERE) grep -E "error|warning|critical" /var/log/syslog grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}" app.log # -P Perl 兼容正则(功能最强) grep -P "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" access.log # 提取IP # -o 只输出匹配部分 grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" access.log # --color=always 高亮显示 grep --color=always "error" /var/log/syslog # 实用:查找所有 failed 登录 grep -i "failed" /var/log/auth.log | grep "ssh" bash
3️⃣ sed — 流编辑器
# 替换:s/旧/新/标志 sed 's/error/ERROR/' file.txt # 每行第一个 sed 's/error/ERROR/g' file.txt # 全局替换 sed 's/error/ERROR/gi' file.txt # 全局+忽略大小写 sed 's/error/ERROR/2' file.txt # 替换每行第2个 # -i 原地修改文件(重要!) sed -i 's/old/new/g' config.conf sed -i.bak 's/old/new/g' config.conf # 备份为 .bak 再修改 # 删除行 sed '/^#/d' config.conf # 删除注释行 sed '/^$/d' config.conf # 删除空行 sed '5d' file.txt # 删除第5行 sed '2,5d' file.txt # 删除2到5行 sed '$d' file.txt # 删除最后一行 # 打印(需要 -n 关闭默认输出) sed -n '5p' file.txt # 打印第5行 sed -n '2,5p' file.txt # 打印2到5行 sed -n '/error/p' file.txt # 打印含 error 的行 bash
# 插入与追加 sed '3i\新插入的行' file.txt # 在第3行前插入 sed '3a\新追加的行' file.txt # 在第3行后追加 sed '/pattern/a\追加到匹配行后' file.txt # 多个操作用 -e 或分号 sed -e '/^#/d' -e '/^$/d' config.conf sed '/^#/d; /^$/d' config.conf # 实用:修改配置文件某参数 sed -i 's/^#\(PermitRootLogin\).*/\1 no/' /etc/ssh/sshd_config # 使用变量 port=8080 sed -i "s/^Port.*/Port $port/" /etc/ssh/sshd_config bash
4️⃣ awk — 文本分析引擎
awk 将每行文本按分隔符切分为字段:$1 第1字段,$2 第2字段,$NF 最后一个字段,$0 整行。
# 基本语法:awk 'pattern { action }' 文件 # 打印特定字段 awk '{print $1, $3}' /etc/passwd # 用默认分隔符(空白) awk -F: '{print $1, $3}' /etc/passwd # 用:作为分隔符 # 内置变量 # NR = 当前行号 NF = 字段总数 # FS = 输入分隔符 OFS = 输出分隔符 # RS = 记录分隔符 ORS = 输出记录分隔符 # FILENAME = 文件名 awk -F: '{print NR, $1, NF}' /etc/passwd awk 'NR>=2 && NR<=5 {print}' file.txt # 打印2到5行 awk 'NF > 3 {print}' file.txt # 字段数大于3的行 bash
# BEGIN 和 END 块 awk 'BEGIN { print "开始处理" } { sum += $1; count++ } END { printf "总和:%d 平均:%.2f\n", sum, sum/count } ' data.txt # 条件过滤 awk -F: '$3 >= 1000 {print "普通用户:", $1}' /etc/passwd # 统计 HTTP 状态码 awk '{print $9}' access.log | sort | uniq -c | sort -rn # 格式化输出 awk -F: '{ printf "%-15s UID: %d\n", $1, $3 }' /etc/passwd # 多分隔符 awk -F'[,:]' '{print $1}' file.txt # 逗号或冒号分隔 bash
# awk 中的数组 # 统计各 IP 访问次数 awk '{ip[$1]++} END { for(i in ip) print ip[i], i }' access.log | sort -rn # awk 控制流 awk '{ if ($1 > 100) { print "大值:", $1 } else { print "小值:", $1 } }' data.txt # awk 实用:提取 nginx 日志慢请求 awk '$NF > 1.0 { print $0 }' nginx_access.log bash
5️⃣ 三剑客组合实战
#!/bin/bash # 实战:分析 nginx 访问日志 LOG="/var/log/nginx/access.log" [[ ! -f "$LOG" ]] && { echo "日志文件不存在"; exit 1; } echo "===== Nginx 访问日志分析 =====" # 1. 总请求数 echo "总请求数:$(wc -l < "$LOG")" # 2. 状态码分布 echo "--- 状态码分布 ---" awk '{print $9}' "$LOG" | sort | uniq -c | sort -rn # 3. 访问量 Top 10 IP echo "--- Top 10 IP ---" awk '{print $1}' "$LOG" | sort | uniq -c | sort -rn | head -10 # 4. 404 请求路径 echo "--- 404 路径 ---" grep ' 404 ' "$LOG" | awk '{print $7}' | sort | uniq -c | sort -rn | head -10 # 5. 每分钟请求量(最近10分钟) echo "--- 最近请求速率 ---" grep "$(date '+%d/%b/%Y:%H:%M' --date='10 minutes ago')" "$LOG" | wc -l bash
🏋️ 今日练习
- 用 grep 从 /var/log/auth.log 提取所有 SSH 登录失败的 IP 地址,去重排序并统计次数
- 用 sed 清理一个配置文件:去除注释行、空行,并将所有 #号注释都删掉
- 用 awk 分析 /etc/passwd,输出 UID 大于 1000 的用户的用户名、UID 和 Shell,用制表符对齐
- 用管道组合:统计 /var/log/syslog 中每个小时出现 error 的次数,格式:
HH: N 次 - 写一个脚本,用 awk 计算 CSV 文件某列数值的总和、平均值、最大值和最小值