Sed 和 Awk 的终极实战:用一行命令搞定90%的文本处理

1. 环境准备与基础概念

1.1 环境检查

首先确认系统已安装必要的工具:

bash 复制代码
# 检查sed版本
sed --version

# 检查awk版本(通常为gawk)
awk --version

# 如果未安装,在Ubuntu/Debian上执行:
sudo apt-get install sed gawk

# 在CentOS/RHEL上执行:
sudo yum install sed gawk

1.2 创建测试文件

为了演示各种操作,我们首先创建测试文件:

bash 复制代码
# 创建员工数据文件
cat > employees.txt << 'EOF'
John Doe,25,Engineer,5000
Jane Smith,30,Manager,7000
Bob Johnson,35,Director,9000
Alice Brown,28,Developer,5500
Mike Wilson,32,Analyst,6000
Sarah Davis,29,Designer,5200
EOF

# 创建日志文件示例
cat > server.log << 'EOF'
2023-10-01 08:30:15 INFO User john logged in from 192.168.1.100
2023-10-01 08:31:22 ERROR Database connection failed
2023-10-01 08:32:45 WARNING Disk usage at 85%
2023-10-01 08:33:10 INFO User jane logged in from 192.168.1.101
2023-10-01 08:34:55 ERROR File not found: /var/www/index.html
2023-10-01 08:35:20 INFO Backup completed successfully
EOF

2. Sed 核心实战技巧

2.1 文本替换与修改

bash 复制代码
# 基础替换:将所有"Engineer"替换为"Software Engineer"
sed 's/Engineer/Software Engineer/g' employees.txt

# 原地修改文件(-i参数)
sed -i 's/Engineer/Software Engineer/g' employees.txt

# 条件替换:只在包含"John"的行进行替换
sed '/John/s/25/26/g' employees.txt

# 多重替换:使用分号分隔多个替换命令
sed 's/John/Jonathan/; s/Manager/Senior Manager/' employees.txt

# 引用匹配内容:保留原内容并添加前缀
sed 's/\([0-9]\{4\}\)$/Salary: \1/' employees.txt

2.2 行操作与过滤

bash 复制代码
# 显示特定行范围(第2-4行)
sed -n '2,4p' employees.txt

# 删除包含特定模式的行
sed '/ERROR/d' server.log

# 在匹配行前后插入内容
sed '/Manager/i\--- Management Team ---' employees.txt
sed '/Manager/a\=======================' employees.txt

# 仅打印匹配的行
sed -n '/INFO/p' server.log

2.3 高级模式处理

bash 复制代码
# 使用正则表达式分组和引用
echo "abc123" | sed 's/\([a-z]*\)[0-9]*/\1/g'

# 处理HTML/XML标签
echo '<div class="header">Title</div>' | sed 's/<[^>]*>//g'

# 处理CSV格式数据
echo '"name,age",city' | sed 's/","/,/g; s/^"//; s/"$//'

3. Awk 高级数据处理

3.1 字段处理基础

bash 复制代码
# 打印特定字段(逗号分隔)
awk -F',' '{print $1, $4}' employees.txt

# 条件过滤:只显示薪资高于6000的员工
awk -F',' '$4 > 6000 {print $1, $4}' employees.txt

# 数值计算:计算平均薪资
awk -F',' '{sum += $4; count++} END {print "Average salary:", sum/count}' employees.txt

# 字符串操作:提取用户名并格式化
awk '{print "User:", toupper($5)}' server.log

3.2 高级数据处理

bash 复制代码
# 分组统计:按职位统计薪资
awk -F',' '
{
    position[$3] += $4
    count[$3]++
}
END {
    for (pos in position) {
        avg = position[pos] / count[pos]
        printf "Position: %-15s Average Salary: %8.2f\n", pos, avg
    }
}' employees.txt

# 时间范围过滤:提取特定时间段的日志
awk '$2 >= "08:32:00" && $2 <= "08:35:00"' server.log

# 复杂条件处理:多条件筛选
awk -F',' '$2 > 25 && $4 < 7000 {print "Candidate:", $1, "Age:", $2, "Salary:", $4}' employees.txt

3.3 报表生成

bash 复制代码
# 生成格式化报表
awk -F',' '
BEGIN {
    print "========================================="
    print "           EMPLOYEE REPORT"
    print "========================================="
    printf "%-15s %-5s %-12s %-10s\n", "Name", "Age", "Position", "Salary"
    print "-----------------------------------------"
}
{
    printf "%-15s %-5d %-12s $%-9d\n", $1, $2, $3, $4
    total_salary += $4
}
END {
    print "-----------------------------------------"
    printf "Total Salary: $%d\n", total_salary
    printf "Average Salary: $%.2f\n", total_salary/NR
}' employees.txt

4. Sed 与 Awk 联合工作流

4.1 管道组合使用

bash 复制代码
# 复杂数据处理流程:提取、转换、过滤
cat server.log | \
sed -n '/ERROR\|WARNING/p' | \
awk '{print $3, $0}' | \
sort | \
uniq -c

# 数据清洗和格式化组合
cat employees.txt | \
sed 's/,/ /g' | \
awk '{print "Name:", $1, $2, "| Monthly:", $4/12, "| Tax:", $4*0.2}'

4.2 实际工作场景示例

bash 复制代码
# 场景1:日志分析报告
cat server.log | \
awk '
/ERROR/ {errors++}
/WARNING/ {warnings++}
/INFO/ {infos++}
END {
    print "=== LOG ANALYSIS REPORT ==="
    print "Errors:", errors
    print "Warnings:", warnings  
    print "Info messages:", infos
    print "Total lines:", NR
}'

# 场景2:数据迁移格式转换
cat employees.txt | \
sed '1i\name,age,position,salary,department' | \
awk -F',' 'NR>1 {print $1 "," $2 "," $3 "," $4 ",IT"}'

5. 文本处理流程图解

以下流程图展示了Sed和Awk在处理文本数据时的完整工作流程:

flowchart TD A[输入文本数据] --> B{数据类型判断} B -->|结构化数据| C[Awk字段处理] B -->|非结构化数据| D[Sed模式处理] C --> E[Awk内置函数] D --> F[Sed正则替换] E --> G[条件判断与循环] F --> H[行级操作] G --> I[数据计算统计] H --> J[文本转换] I --> K{是否需要输出处理} J --> K K -->|是| L[格式化输出] K -->|否| M[数据存储] L --> N[最终结果] M --> N style A fill:#4CAF50,stroke:#388E3C style N fill:#2196F3,stroke:#1976D2 style B fill:#FF9800,stroke:#F57C00 style C fill:#9C27B0,stroke:#7B1FA2 style D fill:#9C27B0,stroke:#7B1FA2

6. 实战案例集合

6.1 系统管理自动化

bash 复制代码
# 磁盘监控和警报
df -h | awk '
NR>1 {
    gsub(/%/,"",$5)
    if ($5 > 80) {
        print "ALERT: Partition", $1, "is", $5 "% full -", $4 " available"
    }
}'

# 进程监控
ps aux | awk '
NR>1 {
    cpu = $3
    mem = $4
    if (cpu > 5.0 || mem > 10.0) {
        printf "High resource process: %s (CPU: %s%%, MEM: %s%%)\n", $11, cpu, mem
    }
}'

6.2 数据处理管道

bash 复制代码
# 创建复杂数据处理脚本
process_data() {
    local input_file=$1
    
    cat "$input_file" | \
    sed '
        # 清理数据
        s/\s\+/ /g
        s/^[[:space:]]*//
        s/[[:space:]]*$//
        # 标准化格式
        s/, /,/g
    ' | \
    awk -F',' '
    BEGIN { print "Processing started..." }
    NF >= 4 {
        # 数据验证和处理
        if ($2 ~ /^[0-9]+$/ && $4 ~ /^[0-9]+$/) {
            processed++
            print $0
        } else {
            invalid++
        }
    }
    END {
        print "Processed:", processed, "records"
        print "Invalid:", invalid, "records"
    }'
}

# 使用函数
process_data employees.txt

6.3 配置文件管理

bash 复制代码
# 更新配置文件参数
update_config() {
    local config_file=$1
    local key=$2
    local value=$3
    
    # 检查键是否存在
    if grep -q "^$key=" "$config_file"; then
        # 更新现有配置
        sed -i "s/^$key=.*/$key=$value/" "$config_file"
    else
        # 添加新配置
        echo "$key=$value" >> "$config_file"
    fi
}

# 批量更新配置
update_configs() {
    local config_file=$1
    shift
    
    while [ $# -gt 0 ]; do
        key=$1
        value=$2
        shift 2
        update_config "$config_file" "$key" "$value"
    done
}

7. 高级技巧与最佳实践

7.1 性能优化

bash 复制代码
# 批量处理大文件(减少IO操作)
process_large_file() {
    local input_file=$1
    
    # 一次性处理多个操作
    awk '
    {
        # 多个数据处理步骤
        gsub(/old_pattern/, "new_pattern")
        
        if ($0 ~ /important/) {
            # 条件处理
            print "IMPORTANT:", $0
        } else {
            print $0
        }
    }
    ' "$input_file" > "${input_file}.processed"
}

# 内存优化处理
memory_efficient_process() {
    local input_file=$1
    
    while IFS= read -r line; do
        # 逐行处理,内存友好
        echo "$line" | sed 's/pattern/replacement/'
    done < "$input_file"
}

7.2 错误处理与调试

bash 复制代码
# 带错误检查的sed脚本
safe_sed_replace() {
    local pattern=$1
    local replacement=$2
    local file=$3
    
    # 备份原文件
    cp "$file" "${file}.backup"
    
    # 执行替换并检查结果
    if sed -i "s/$pattern/$replacement/g" "$file"; then
        echo "Successfully replaced '$pattern' with '$replacement'"
        
        # 验证更改
        local changes=$(diff -u "${file}.backup" "$file" | grep -c '^+[^+]')
        echo "Made $changes changes"
    else
        echo "Error: Replacement failed" >&2
        # 恢复备份
        mv "${file}.backup" "$file"
        return 1
    fi
}

# Awk脚本调试技巧
debug_awk_script() {
    local script=$1
    local data_file=$2
    
    awk -v DEBUG=1 '
    function debug(message) {
        if (DEBUG) {
            print "DEBUG: " message > "/dev/stderr"
        }
    }
    
    {
        debug("Processing line: " NR)
        # 你的awk代码在这里
        debug("Field count: " NF)
    }
    ' "$script" "$data_file"
}

8. 总结与进阶学习

通过本教程,已经掌握了Sed和Awk在文本处理中的核心应用。这些一行命令的组合能够解决实际工作中90%的文本处理需求。关键要点总结:

  1. Sed擅长:模式匹配、文本替换、行级操作
  2. Awk擅长:字段处理、数据计算、复杂报表
  3. 组合使用:通过管道将两者结合,发挥最大威力
  4. 实践建议:从简单任务开始,逐步构建复杂的数据处理管道

继续深入学习建议探索:

  • 正则表达式高级用法
  • Awk关联数组和函数定义
  • Sed的高级模式空间和保持空间操作
  • 性能优化和大型文件处理技巧

记住,熟练掌握这些工具的关键在于持续实践和应用于真实场景。

相关推荐
A小辣椒2 天前
TShark:Wireshark CLI 功能
linux
A小辣椒2 天前
TShark:基础知识
linux
AlfredZhao2 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao3 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334663 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪3 天前
linux 拷贝文件或目录到指定的位置
linux
摇滚侠4 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush44 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5204 天前
Linux 11 动态监控指令top
linux
不会C语言的男孩4 天前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言