【Linux】Shell编程(二):grep - 文本搜索利器
本专栏文章持续更新,新增内容使用蓝色表示。
1. 什么是grep?
grep(Global Regular Expression Print)是Linux系统中最强大、最常用的文本搜索工具。它的核心功能就是在文件中查找指定的文本模式,并将匹配的行打印出来。
为什么叫grep? 这个名字来源于ed编辑器中的命令 g/re/p(global/regular expression/print),意为"全局正则表达式打印"。
2. 基础用法
2.1 最简单的文本搜索
# 在file.txt中查找包含"success"的行
grep "success" file.txt
示例:
# 假设我们有一个日志文件
echo "Server started successfully
Database connection failed
User login successful
Database connection timeout" > app.log# 查找所有包含"Database"的行
grep "Database" app.log
输出:
Database connection failed
Database connection timeout
2.2 实用的搜索选项
# 忽略大小写(-i)
grep -i "error" app.log # 匹配error、Error、ERROR等# 显示行号(-n)
grep -n "failed" app.log # 显示匹配行在文件中的位置# 统计匹配次数(-c)
grep -c "success" app.log # 只显示匹配了多少行# 反向匹配(-v)
grep -v "INFO" app.log # 显示不包含"INFO"的行# 精确匹配单词(-w)
grep -w "line" file.txt # 只匹配"line",不匹配"inline"或"pipeline"
2.3 递归搜索和多文件处理
# 在当前目录及所有子目录中搜索
grep -r "TODO" ./# 只显示包含匹配内容的文件名(-l)
grep -l "critical" *.log # 只列出文件名,不显示具体内容
# 在当前目录所有.log文件中搜索
grep "error" *.log# 在多个指定文件中搜索
grep "pattern" file1.log file2.log file3.log# 在不同类型文件中搜索
grep "TODO" *.txt *.md *.py
3. 正则表达式:解锁高级搜索能力
3.1 基础正则表达式
# 行首匹配(^)
grep "^2023" logfile.txt # 查找以"2023"开头的行# 行尾匹配($)
grep "success$" logfile.txt # 查找以"success"结尾的行# 任意字符(.)
grep "f..l" file.txt # 匹配f+任意字符+任意字符+l,如"fail"、"fall"、"full"# 字符集合
grep "[aeiou]" file.txt # 包含任意元音字母的行
grep "[0-9]" file.txt # 包含数字的行
grep "[^0-9]" file.txt # 不包含数字的行# 查找空行
grep "^$" file.txt
3.2 扩展正则表达式
使用 grep -E 或 egrep:
# 一个或多个(+)
grep -E "a+" file.txt # 匹配1个或多个连续的a# 零个或一个(?)
grep -E "colou?r" file.txt # 匹配"color"或"colour"# 或操作(|)
grep -E "error|fail|critical" logfile.txt # 匹配任意一个关键词# 指定次数范围
grep -E "a{2,5}" file.txt # 匹配2到5个连续的a# 分组
grep -E "(ab)+" file.txt # 匹配"ab"、"abab"、"ababab"等
3.3 实战:查找特定格式的数据
# 查找IP地址
grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" access.log# 查找邮箱地址
grep -E "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" users.txt# 查找时间格式(HH:MM:SS)
grep -E "([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]" logfile.txt
4. 生产环境实战案例
4.1 系统监控和日志分析
grep -q 是 静默模式(quiet mode),它执行搜索但不输出任何结果,只通过退出状态码来告诉你是否找到了匹配内容。
将前一个命令的输出作为参数,替换 {} 占位符。
场景: 监控系统日志,自动生成健康报告
#!/bin/bash
# monitor_system.shLOG_FILE="system_monitor.log"echo "=== 系统监控报告 ==="
echo "生成时间:$(date)"# 统计不同级别的日志数量
echo "日志级别统计:"
grep -c "ERROR" "$LOG_FILE" | xargs echo " 错误(ERROR):{} 条"
grep -c "WARNING" "$LOG_FILE" | xargs echo " 警告(WARNING):{} 条"
grep -c "CRITICAL" "$LOG_FILE" | xargs echo " 严重(CRITICAL):{} 条"# 检查严重问题
echo -e "\n严重问题检查:"
if grep -q "CRITICAL" "$LOG_FILE"; thenecho "⚠️ 发现严重问题:"grep "CRITICAL" "$LOG_FILE"
elseecho "✅ 无严重问题"
fi# 资源使用分析
echo -e "\n资源使用警告:"
grep "WARNING" "$LOG_FILE" | grep -E "usage|space" || echo "✅ 资源使用正常"
使用方法:
# 创建测试日志
cat > system_monitor.log << 'EOF'
2023-10-01 08:00:01 INFO System started successfully
2023-10-01 08:15:23 WARNING High memory usage detected
2023-10-01 08:30:45 ERROR Database connection failed
2023-10-01 09:00:12 CRITICAL System overload - CPU 95%
EOF# 运行监控脚本
chmod +x monitor_system.sh
./monitor_system.sh
4.2 网络安全分析
场景: 分析SSH登录尝试,检测暴力破解攻击
#!/bin/bash
# analyze_security.shSECURITY_LOG="security.log"echo "=== 网络安全分析报告 ==="
echo "分析时间:$(date)"# 基础统计
FAILED_ATTEMPTS=$(grep -c "Failed password" "$SECURITY_LOG")
SUCCESSFUL_LOGINS=$(grep -c "Accepted password" "$SECURITY_LOG")echo "登录统计:"
echo " 失败登录尝试:$FAILED_ATTEMPTS 次"
echo " 成功登录:$SUCCESSFUL_LOGINS 次"# 攻击源分析
echo -e "\n攻击源IP分析:"
grep "Failed password" "$SECURITY_LOG" | grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sort | uniq -c | sort -nr | head -5
-o:只输出匹配的部分
正则表达式: [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+
[0-9]+:1个或多个数字
\.:字面意义的点号(IP地址中的点)
sort:排序
-n:按数值排序
-r:反向排序(降序)
uniq:去重
-c:统计次数
创建测试数据:
# 生成测试安全日志
cat > security.log << 'EOF'
Oct 1 08:00:01 server sshd[1234]: Failed password for root from 192.168.1.100 port 22 ssh2
Oct 1 08:00:15 server sshd[1235]: Failed password for admin from 192.168.1.101 port 22 ssh2
Oct 1 08:01:01 server sshd[1237]: Accepted password for john from 192.168.1.50 port 22 ssh2
EOFchmod +x analyze_security.sh
./analyze_security.sh
实时监控版本:
#!/bin/bash
# 可配置时间窗口的SSH监控SECURITY_LOG="/var/log/auth.log"
THRESHOLD=5
TIME_WINDOW="1 hour" # 可配置:1 hour, 30 minutes, 2 hoursget_time_pattern() {local window="$1"date '+%b %e %H:' --date="$window ago"
}count_recent_attempts() {local ip="$1"local time_pattern=$(get_time_pattern "$TIME_WINDOW")grep "Failed password" "$SECURITY_LOG" | \grep "$ip" | \grep "$time_pattern" | \wc -l
}echo "🔍 启动SSH攻击监控(时间窗口: $TIME_WINDOW)..."tail -F "$SECURITY_LOG" | while read line; doif echo "$line" | grep -q "Failed password"; thenIP=$(echo "$line" | grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")COUNT=$(count_recent_attempts "$IP")if [ $COUNT -ge $THRESHOLD ]; thenecho "🚨 实时警报: $IP 在${TIME_WINDOW}内尝试 $COUNT 次"fifi
done
4.3 高级技巧和性能优化
# 1. 静默模式 - 用于脚本中的条件判断
grep -q "pattern" file.txt && echo "找到" || echo "未找到"# 2. 显示匹配行的上下文
grep -C 3 "error" logfile.txt # 显示匹配行前后各3行
grep -A 2 "exception" logfile.txt # 显示匹配行后2行
grep -B 2 "warning" logfile.txt # 显示匹配行前2行# 3. 高亮显示匹配内容
grep --color=auto "critical" logfile.txt# 4. 处理二进制文件中的文本
grep -a "text" binary.file
-a 选项告诉 grep 将二进制文件当作文本文件来处理,强制在二进制内容中搜索文本模式。
# 5. 排除某些文件或目录
grep -r --exclude-dir=".git" "TODO" ./
grep -r --include="*.java" "public class" ./
-r:递归搜索
--exclude-dir=".git":排除 .git 目录
./:从当前目录开始搜索
--include="*.java":只搜索Java文件
5. 补充
5.1 性能优化技巧
# 使用fgrep加快固定字符串搜索(不使用正则表达式)
fgrep "固定文本" large_file.log# 限制搜索深度
grep -r --max-depth=2 "pattern" ./# 使用并行处理处理大文件
cat large_file.log | parallel --pipe grep "pattern"
5.2 错误处理和健壮性
#!/bin/bashsearch_pattern() {local pattern="$1"local file="$2"# 参数检查if [[ -z "$pattern" || -z "$file" ]]; thenecho "错误:缺少参数" >&2return 1fi# 文件存在性检查if [[ ! -f "$file" ]]; thenecho "错误:文件 $file 不存在" >&2return 1fi# 执行搜索,处理错误if grep -q "$pattern" "$file"; thenecho "找到匹配内容"return 0elseecho "未找到匹配内容"return 1fi
}
5.3 自动化监控示例
#!/bin/bash
# 自动化日志监控LOG_FILE="/var/log/application.log"
ALERT_PATTERNS="CRITICAL|FATAL|OutOfMemoryError"
REPORT_FILE="/tmp/log_report_$(date +%Y%m%d_%H%M%S).txt"# 监控最新日志内容
tail -n 1000 "$LOG_FILE" | grep -E "$ALERT_PATTERNS" > "$REPORT_FILE"# 如果有匹配内容,发送警报
if [[ -s "$REPORT_FILE" ]]; thenecho "发现关键错误,发送警报..."# 这里可以集成别的通知方式cat "$REPORT_FILE"
fi
在实际企业环境中,推荐使用专业的监控平台 Prometheus + Alertmanager - 云原生监控标准,Zabbix - 传统企业级监控方案。
如有问题或建议,欢迎在评论区中留言~