Shell脚本如何从日志提取关键字段

wen 实用脚本 1

本文目录导读:

Shell脚本如何从日志提取关键字段

  1. 使用grepawk提取字段
  2. 使用sed进行复杂提取
  3. 完整的日志解析脚本
  4. 提取结构化日志(JSON格式)
  5. 高级提取示例
  6. 实时日志监控提取
  7. 常用的提取技巧
  8. 使用建议

我来介绍几种从日志中提取关键字段的Shell脚本方法:

使用grepawk提取字段

基本格式提取

#!/bin/bash
# 假设日志格式: [2024-01-15 10:30:45] ERROR: 用户ID=12345 操作=登录 IP=192.168.1.1
# 提取所有ERROR级别的日志
grep "ERROR" app.log
# 提取特定字段(用户ID)
grep "ERROR" app.log | awk '{print $4}'
# 使用awk按分隔符提取
awk -F'=' '{print $2}' app.log | awk '{print $1}'

使用sed进行复杂提取

#!/bin/bash
# 提取IP地址
sed -n 's/.*IP=\([0-9.]*\).*/\1/p' app.log
# 提取时间戳
sed -n 's/\[\(.*\)\].*/\1/p' app.log
# 提取特定模式之间的内容
sed -n 's/.*用户ID=\([0-9]*\).*/\1/p' app.log

完整的日志解析脚本

#!/bin/bash
# 日志分析脚本
LOG_FILE="application.log"
# 提取错误日志并格式化
echo "===== 错误日志分析 ====="
grep "ERROR" "$LOG_FILE" | while read line; do
    # 提取时间
    timestamp=$(echo "$line" | grep -oP '\[\K[^\]]+')
    # 提取用户ID
    user_id=$(echo "$line" | grep -oP '用户ID=\K[0-9]+')
    # 提取操作类型
    action=$(echo "$line" | grep -oP '操作=\K[^ ]+')
    # 提取IP
    ip=$(echo "$line" | grep -oP 'IP=\K[0-9.]+')
    echo "时间: $timestamp | 用户: $user_id | 操作: $action | IP: $ip"
done
# 统计各操作次数
echo -e "\n===== 操作统计 ====="
grep -oP '操作=\K[^ ]+' "$LOG_FILE" | sort | uniq -c | sort -rn

提取结构化日志(JSON格式)

#!/bin/bash
# 处理JSON格式日志
# 示例: {"timestamp":"2024-01-15","level":"ERROR","user":"12345","action":"login","ip":"192.168.1.1"}
cat app.log | while read line; do
    # 提取JSON字段
    level=$(echo "$line" | python3 -c "import sys,json; print(json.load(sys.stdin)['level'])" 2>/dev/null)
    user=$(echo "$line" | python3 -c "import sys,json; print(json.load(sys.stdin)['user'])" 2>/dev/null)
    # 或者使用jq工具
    level=$(echo "$line" | jq -r '.level')
    user=$(echo "$line" | jq -r '.user')
    if [ "$level" == "ERROR" ]; then
        echo "Error by user: $user"
    fi
done

高级提取示例

#!/bin/bash
# 综合提取脚本
extract_patterns() {
    local log_file=$1
    # 定义提取模式
    patterns=(
        "IP地址:IP=\K[0-9.]+"
        "邮箱:[\w._%+-]+@[\w.-]+\.[A-Za-z]{2,}"
        "订单号:ORD-\K[0-9]{8}"
        "金额:\$\K[0-9.]+"
        "电话号码:1[3-9]\K[0-9]{9}"
    )
    echo "===== 字段提取结果 ====="
    # 遍历所有模式
    for pattern in "${patterns[@]}"; do
        field_name=$(echo "$pattern" | cut -d: -f1)
        regex=$(echo "$pattern" | cut -d: -f2)
        echo -e "\n提取 $field_name:"
        grep -oP "$regex" "$log_file" | sort | uniq -c | sort -rn | head -10
    done
    # 统计提取总数
    echo -e "\n===== 统计信息 ====="
    total_lines=$(wc -l < "$log_file")
    echo "总日志行数: $total_lines"
}
# 使用函数
extract_patterns "application.log"

实时日志监控提取

#!/bin/bash
# 实时监控并提取字段
tail -f application.log | while read line; do
    # 检测并提取关键信息
    if echo "$line" | grep -q "ERROR"; then
        timestamp=$(echo "$line" | grep -oP '\[\K[^\]]+')
        message=$(echo "$line" | grep -oP 'ERROR:\s*\K.*')
        # 告警或记录
        echo "[ALERT] $timestamp - $message" >> error_alerts.log
        # 发送邮件或通知
        # echo "Error detected: $message" | mail -s "Error Alert" admin@example.com
    fi
done

常用的提取技巧

#!/bin/bash
# 1. 提取两个关键字之间的内容
grep -oP 'START\K.*?END' logfile
# 2. 提取固定列(使用cut)
cut -d' ' -f3-5 logfile
# 3. 多条件组合提取
awk '/ERROR/ && /user123/' logfile
# 4. 提取并格式化输出
awk '{
    split($0, arr, " ")
    for (i in arr) {
        if (arr[i] ~ /^ERROR/) print "Level:", arr[i]
        if (arr[i] ~ /^User:/) print "User:", substr(arr[i], 6)
    }
}' logfile

使用建议

  1. 性能考虑:对于大文件,优先使用awkgrep而不是循环
  2. 正则测试:使用-o选项测试正则是否正确
  3. 数据验证:提取后增加验证步骤,确保数据完整性
  4. 错误处理:添加文件存在检查等错误处理

需要根据具体的日志格式调整提取方法和正则表达式。

抱歉,评论功能暂时关闭!