grep 命令小结

一、命令介绍与原理

介绍

  grep(Global Regular Expression Print)是 Linux 系统中最强大的文本搜索工具,用于在文件或标准输入中查找匹配指定模式的行。它是文本处理和数据提取的核心工具,几乎每个 Linux 用户都会频繁使用。

工作原理

  • 模式匹配引擎:使用高效的字符串匹配算法(如 Boyer-Moore、正则表达式引擎)
  • 行缓冲处理:逐行读取输入,应用模式匹配
  • 流式处理:支持管道输入,可以处理大型文件
  • 多算法支持:支持固定字符串、基本正则表达式(BRE)、扩展正则表达式(ERE)

二、基本语法

grep [选项] 模式 [文件...]

 

常用选项


# 搜索控制选项
-i, --ignore-case      # 忽略大小写
-v, --invert-match     # 反向匹配,显示不包含模式的行
-w, --word-regexp      # 匹配完整单词
-x, --line-regexp      # 匹配整行
-F, --fixed-strings    # 将模式视为固定字符串
-G, --basic-regexp     # 使用基本正则表达式(默认)
-E, --extended-regexp  # 使用扩展正则表达式
-P, --perl-regexp      # 使用Perl兼容正则表达式
# 输出控制选项
-n, --line-number      # 显示行号
-H, --with-filename    # 显示文件名
-h, --no-filename      # 不显示文件名
-c, --count            # 只显示匹配行数
-l, --files-with-matches   # 只显示包含匹配的文件名
-L, --files-without-match  # 只显示不包含匹配的文件名
-o, --only-matching    # 只输出匹配的部分
--color[=WHEN]         # 高亮显示匹配文本
# 上下文控制
-A NUM, --after-context=NUM   # 显示匹配行后的NUM行
-B NUM, --before-context=NUM  # 显示匹配行前的NUM行
-C NUM, --context=NUM         # 显示匹配行前后的NUM行
# 文件处理选项
-r, --recursive        # 递归搜索目录
-R, --dereference-recursive # 递归并跟随符号链接
--include=GLOB         # 只搜索匹配GLOB的文件
--exclude=GLOB         # 跳过匹配GLOB的文件
--exclude-dir=DIR      # 跳过匹配的目录

三、经典使用场景

3.1 基本文本搜索

# 在文件中搜索字符串
grep "error" logfile.log
# 忽略大小写搜索
grep -i "warning" application.log
# 搜索完整单词
grep -w "class" source_code.java

3.2 多文件搜索

# 在多个文件中搜索
grep "pattern" file1.txt file2.txt file3.txt
# 使用通配符
grep "TODO" *.py
# 递归搜索目录
grep -r "function" /home/user/projects/

3.3 上下文显示

# 显示匹配行及其后3行
grep -A 3 "Exception" traceback.log
# 显示匹配行及其前2行
grep -B 2 "segmentation fault" system.log
# 显示匹配行前后各2行
grep -C 2 "connection refused" network.log

四、与其他工具命令结合使用

4.1 与 find 结合

# 在找到的文件中搜索内容
find /var/log -name "*.log" -exec grep -H "error" {} \;
# 使用xargs提高效率
find . -name "*.java" -print0 | xargs -0 grep -l "interface"
# 组合搜索和过滤
find /etc -type f -exec grep -q "password" {} \; -print

4.2 与 awk/sed 结合

# 从 ps aux 输出中提取第11列(命令列),然后过滤出包含"python"字符串的行
ps aux | awk '{print $11}' | grep "python"
# 搜索后替换
grep -l "old_string" *.txt | xargs sed -i 's/old_string/new_string/g'
# 复杂数据处理
grep "ERROR" app.log | awk '{print $1, $5}' | sort | uniq -c

4.3 与 sort/uniq 结合

# 统计错误类型频率
grep -o "ERROR:.*" application.log | sort | uniq -c | sort -nr
# 提取唯一IP地址
grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" access.log | sort -u

4.4 在脚本中结合使用

#!/bin/bash
# 日志分析脚本
analyze_logs() {
    local log_file="$1"
    echo "=== 错误统计 ==="
    grep -c "ERROR" "$log_file"
    echo "=== 最近错误 ==="
    grep -A 2 -B 2 "ERROR" "$log_file" | tail -10
    echo "=== 唯一错误消息 ==="
    grep -o "ERROR: .*" "$log_file" | sort -u
}

例如:

# 1. 保存为 run.sh
# 2. 给予执行权限
chmod +x run.sh
# 3. 执行脚本(必须提供日志文件参数)
./run.sh /var/log/your_app.log
# 如果没有参数会显示错误
./run.sh
# 输出: 错误: 请指定日志文件路径
注释:locallog_file="$1"

$1 是脚本的第一个位置参数
当执行 ./run.sh /var/log/app.log 时:
$0 = ./run.sh (脚本名)
$1 = /var/log/app.log (第一个参数)
$2 = 第二个参数(如果有)
以此类推...

五、进阶应用场景
5.1 复杂正则表达式

# 匹配Email地址
grep -E "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z]{2,}\b" contacts.txt
# 匹配IP地址
grep -E "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" config_files/*
# 匹配URL
grep -E "https?://[a-zA-Z0-9./?=_-]*" web_logs.txt
# 匹配时间格式
grep -E "([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]" logfile.log

5.2 高级日志分析

#!/bin/bash
# 生产环境日志分析
production_log_analysis() {
    local log_file="$1"  # 执行脚本必须提供分析的日志文件 
    local output_dir="/var/log/analysis"
    mkdir -p "$output_dir"
    # 提取关键指标
    local total_requests=$(grep -c "request" "$log_file")
    local error_requests=$(grep -c "ERROR" "$log_file")
    local slow_requests=$(grep "processing_time" "$log_file" | awk '$NF > 5.0' | wc -l)
    # 生成报告
    cat > "$output_dir/report_$(date +%Y%m%d).txt" << EOF
日志分析报告 - $(date)
========================
总请求数: $total_requests
错误请求: $error_requests
慢请求(>5s): $slow_requests
错误率: $(echo "scale=2; $error_requests * 100 / $total_requests" | bc)%
EOF
    # 提取错误详情
    grep -A 3 -B 1 "ERROR" "$log_file" > "$output_dir/error_details.txt"
    # 提取性能数据
    grep "processing_time" "$log_file" | awk '{print $NF}' > "$output_dir/response_times.txt"
}

5.3 代码审查和质量检查

#!/bin/bash
# 代码质量检查工具
code_quality_check() {
    local project_dir="$1"
    echo "=== 代码质量检查 ==="
    # 查找TODO和FIXME注释
    echo "待办事项:"
    grep -r -n "TODO\|FIXME" "$project_dir" --include="*.py" --include="*.java"
    # 查找调试代码
    echo "可能的调试代码:"
    grep -r -n "print(\|console.log\|alert(" "$project_dir" --include="*.py" --include="*.js"
    # 查找硬编码密码
    echo "硬编码凭证检查:"
    grep -r -i "password.*=" "$project_dir" --include="*.py" --include="*.java" | grep -v "#"
    # 查找过时的API调用
    echo "过时API检查:"
    grep -r -n "deprecated\|obsolete" "$project_dir" --include="*.java"
}

5.4 安全审计脚本


#!/bin/bash
# 系统安全扫描
security_scan() {
    local scan_dir="$1"
    echo "=== 安全扫描开始 ==="
    # 查找可能的敏感信息
    echo "查找敏感信息..."
    grep -r -i "password\|secret\|key\|token" "$scan_dir" \
        --include="*.conf" --include="*.yml" --include="*.json" \
        --exclude-dir=".git" 2>/dev/null
    # 查找可疑的PHP函数
    echo "查找可疑PHP代码..."
    grep -r -n "eval(\|system(\|exec(\|shell_exec(" "$scan_dir" \
        --include="*.php" 2>/dev/null
    # 查找潜在的SSH密钥
    echo "查找SSH私钥..."
    grep -r -l "BEGIN.*PRIVATE KEY" "$scan_dir" 2>/dev/null
    # 查找数据库连接字符串
    echo "查找数据库连接信息..."
    grep -r -E "mysql://|postgresql://|mongodb://" "$scan_dir" \
        --exclude-dir=".git" 2>/dev/null
    echo "=== 安全扫描完成 ==="
}

六、实用技巧和示例

6.1 性能监控和分析

#!/bin/bash
# 系统性能监控
performance_monitor() {
    local log_file="$1"
    echo "=== 性能分析 ==="
    # 提取响应时间
    echo "响应时间分布:"
    grep -o "response_time=[0-9.]*" "$log_file" | cut -d= -f2 | sort -n | \
    awk '
    {
        total += $1
        count++
        values[count] = $1
    }
    END {
        if (count > 0) {
            print "平均: " total/count "ms"
            print "中位数: " values[int(count/2)] "ms"
            print "95百分位: " values[int(count*0.95)] "ms"
            print "最大: " values[count] "ms"
        }
    }'
    # 错误率分析
    local total_lines=$(wc -l < "$log_file")
    local error_lines=$(grep -c "ERROR" "$log_file")
    echo "错误率: $(echo "scale=2; $error_lines * 100 / $total_lines" | bc)%"
}

6.2 数据提取和转换

#!/bin/bash
# 数据提取工具
data_extractor() {
    local source_file="$1"
    local output_format="$2"
    case "$output_format" in
        "emails")
            # 提取Email地址
            grep -o -E "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z]{2,}\b" "$source_file" | sort -u
            ;;
        "urls")
            # 提取URL
            grep -o -E "https?://[a-zA-Z0-9./?=_-]*" "$source_file" | sort -u
            ;;
        "ips")
            # 提取IP地址
            grep -o -E "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" "$source_file" | sort -u
            ;;
        "phones")
            # 提取电话号码
            grep -o -E "(\+?[0-9]{1,3}[-. ]?)?\(?[0-9]{3}\)?[-. ]?[0-9]{3}[-. ]?[0-9]{4}" "$source_file"
            ;;
        *)
            echo "不支持的格式: $output_format"
            return 1
            ;;
    esac
}

6.3 与其他命令的对比

# grep vs ack/ag/rg
grep -r "pattern"  # 简单快速的文本搜索,支持正则表达式。
ack "pattern"      # 专为代码搜索设计,默认会忽略版本控制目录(如.git)和备份文件等。
ag "pattern"       # 类似于ack,但速度更快,同样会忽略一些不需要搜索的目录。
rg "pattern"       # ripgrep,速度非常快,同样会忽略.gitignore中指定的文件,并且支持很多现代特性。

# grep vs sed
grep "pattern" file     # 搜索和过滤
sed -n '/pattern/p' file  # 流编辑器,不仅可以搜索,还可以进行文本替换、删除等操作。

# grep vs awk
grep "pattern" file   # 简单的行匹配
awk '/pattern/' file  # 更强大的文本处理工具,可以按列处理文本,支持编程结构。

七、总结

通过深入掌握 grep 命令,可以构建强大的文本处理和分析工作流。无论是简单的字符串搜索还是复杂的日志分析,grep 都提供了可靠高效的解决方案。虽然现代替代工具如 ripgrep 在某些场景下性能更好,但 grep 的普及性和标准化使其仍然是大多数 Linux 环境中的首选工具。

posted @ 2025-12-05 04:11  hihibig  阅读(20)  评论(0)    收藏  举报