目录
一、grep:文本搜索的瑞士军刀
1. 正则表达式引擎详解
基础正则表达式(BRE):
bash
grep 'http' access.log # 基础模式匹配
grep '^192\.168' access.log # 转义字符需反斜杠
扩展正则表达式(ERE):
bash
grep -E 'http|https' access.log # 或操作
grep -E '(error|warning):' system.log # 分组匹配
2. 高级搜索模式
上下文控制:
bash
grep -A 3 'ERROR' app.log # 显示匹配行及后3行
grep -B 2 'START' data.txt # 显示匹配行及前2行
文件类型过滤:
bash
grep -r --include='*.conf' 'port' /etc/ # 递归搜索.conf文件
3. 性能优化技巧
固定字符串模式:
bash
grep -F 'GET /api' access.log # 禁用正则,提升速度
并行处理:
bash
grep --mmap 'pattern' largefile.log # 使用内存映射加速
二、awk:列处理大师的终极指南
1. 执行流程解析
awk
BEGIN {
FS=":" # 设置字段分隔符
OFS="|" # 输出分隔符
print "START PROCESSING"
}
{
# 主输入循环
if ($3 > 1000) {
print $1, $3*2 # 自动使用OFS分隔
}
}
END {
print "END PROCESSING"
print NR " records processed"
}
2. 高级字段操作
动态分隔符:
awk
awk -F'[:,]' '{print $1, $3}' data.csv # 复合分隔符
字段重组:
awk
awk '{ $1="NEW"; print $0 }' OFS=',' data.txt # 修改首列
3. 复杂日志分析示例
假设日志格式:
192.168.1.1 - - [10/May/2025:08:35:22 +0800] "GET /api/data HTTP/1.1" 200 1024 "https://example.com" "Mozilla/5.0" 0.123
awk
awk '{
# 提取完整时间戳
timestamp = $4 " " $5
# 解析响应时间(最后一列)
resp_time = $NF
# 计算每小时请求量
hour = substr($4, 1, 2)
count[hour]++
# 统计状态码分布
status_code[$9]++
# 输出格式化记录
printf "%s %s %.3f\n", $1, timestamp, resp_time
}' access.log | awk '
# 二次处理统计结果
{
total++
sum += $3
}
END {
print "Total Requests:", total
print "Average Response Time:", sum/total
for (h in count) print h ":00 - " count[h] " requests"
}
三、sed:流式编辑器的黑魔法
1. 地址匹配系统
行号范围:
sed
sed '5,10d' file.txt # 删除5-10行
sed '10,$s/foo/bar/' file # 从第10行到末尾替换
模式空间操作:
sed
sed '/start/,/end/{
/exclude/d # 排除特定行
s/old/new/g # 范围内替换
}' data.txt
2. 高级编辑命令
多命令组合:
sed
sed -e 's/foo/bar/' -e 's/baz/qux/' file # 链式处理
保持空间操作:
sed
h # 复制模式空间到保持空间
$!d # 删除除最后一行外的所有行
G # 从保持空间追加内容
s/\n/ / # 合并两行
' file.txt # 实现行合并
3. 实际应用案例
CSV格式转换:
sed
sed -E '
s/","/|/g # 替换字段分隔符
s/^"|"$//g # 去除首尾引号
s/\\"/"/g # 处理转义引号
' data.csv > data.tsv
XML标签清理:
sed
sed '
s/<[^>]\+>//g # 删除所有XML标签
s/^[ \t]*// # 去除行首空白
s/[ \t]*$// # 去除行尾空白
' xmlfile.txt
四、自动化脚本实战进阶
1. 防御性脚本设计
bash
#!/bin/bash
# 文件名:advanced_log_analyzer.sh
LOG_DIR="/var/log/nginx"
REPORT_DIR="./reports"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# 创建报告目录
mkdir -p "$REPORT_DIR" || {
echo "错误:无法创建报告目录 $REPORT_DIR"
exit 1
}
# 日志文件验证
find "$LOG_DIR" -name "access.log*" -type f -mtime -1 | while read -r LOG_FILE; do
# 生成唯一报告文件
REPORT_FILE="$REPORT_DIR/report_${TIMESTAMP}_$(basename $LOG_FILE).txt"
# 使用临时文件避免中断丢失数据
TEMP_FILE=$(mktemp)
awk '{
# 复杂分析逻辑
ip = $1
status = $9
size = $10
time = $NF
# 统计指标
total_requests++
total_bytes += size
status_count[status]++
ip_count[ip]++
time_sum += time
# 生成详细记录
printf "%s %s %s %.3f\n", ip, $4, status, time
}' "$LOG_FILE" > "$TEMP_FILE"
# 生成汇总报告
{
echo "日志文件: $LOG_FILE"
echo "时间范围: $(date -r $(stat -c %Y "$LOG_FILE") +%F\ %T)"
echo "总请求数: $total_requests"
echo "总传输量: $(numfmt --to=iec-i --suffix=B $total_bytes)"
echo "平均响应时间: $(printf "%.3f" $(echo "$time_sum/$total_requests" | bc -l)) 秒"
echo
echo "状态码分布:"
for code in 200 404 500; do
printf "%4s: %d\n" $code ${status_count[$code]:-0}
done
echo
echo "高频访问IP TOP 10:"
echo "IP地址 请求次数"
for ip in $(sort -k2 -nr <(for i in "${!ip_count[@]}"; do echo "$i ${ip_count[$i]}"; done) | head -n 10 | awk '{print $1}'); do
count=${ip_count[$ip]}
printf "%-15s %d\n" $ip $count
done
} >> "$REPORT_FILE"
# 清理临时文件
rm -f "$TEMP_FILE"
echo "报告生成: $REPORT_FILE"done
echo "所有分析完成,结果保存在 $REPORT_DIR"
2. 脚本增强特性
日志轮转处理:
bash
find "$LOG_DIR" -name "access.log-*" -type f -mtime -7 | while read -r LOG_FILE; do
# 处理历史日志
done----------------------------------------------------------------------------------------
邮件通知集成:
bash
if [ "$ERROR_COUNT" -gt 100 ]; then
echo "错误警报:检测到 $ERROR_COUNT 个错误" | mail -s "系统警报" admin@example.com
fi
五、性能调优与故障排除
1. 工具选择对比
场景 grep awk sed
简单模式匹配 ★★★★★ ★★★☆☆ ★★☆☆☆
复杂列处理 ★★☆☆☆ ★★★★★ ★★★☆☆
流式编辑 ★★☆☆☆ ★★★☆☆ ★★★★★
数学计算 ★☆☆☆☆ ★★★★☆ ★★☆☆☆
2. 大文件处理技巧
使用缓冲优化:
bash
awk --sandbox -v RS='\n' '...' largefile.log # 显式设置行分隔符
并行处理:
bash
split -l 100000 largefile.log chunk_
for f in chunk_*; do
awk '{...}' $f &
done
wait
3. 调试技巧
awk调试模式:
bash
awk -D '{...}' file.txt # 显示详细执行过程
sed脚本验证:
bash
sed -n -e 'l' -e '=p' file.txt # 显示行号和换行符