Shell脚本实现文件差异对比与高亮显示
在软件开发与运维场景中,文件内容对比是高频需求。例如配置文件版本管理、日志差异分析等场景,均需快速定位文件差异。本文将介绍基于Shell脚本的解决方案,结合diff命令与文本处理工具实现高效对比。
基础对比方案:diff命令
diff命令是Linux系统原生支持的文件对比工具,其基本语法为:
diff [选项] 文件1 文件2
常用选项包括:
-u:生成统一格式输出(包含上下文行)-y:并排显示差异(适合终端宽度足够的场景)-i:忽略大小写差异
示例脚本实现:
#!/bin/bashfile1="config_v1.conf"file2="config_v2.conf"# 基础对比(统一格式输出)diff -u "$file1" "$file2" > diff_result.txt# 并排显示对比(需终端支持宽字符)diff -y "$file1" "$file2" | column -t -s $'\t'
进阶方案:差异高亮显示
为提升可读性,可通过colordiff工具或grep+sed组合实现语法高亮。以下是基于grep的轻量级实现:
#!/bin/bashfile1="source.txt"file2="target.txt"# 生成差异标记(红色删除/绿色新增)diff --color=always "$file1" "$file2" | \grep --color=always '^[<>]' | \sed 's/^</\033[31m<\033[0m/; s/^>/\033[32m>\033[0m/'
关键点解析:
--color=always强制输出颜色标记grep过滤差异行(<表示删除,>表示新增)sed通过ANSI转义码实现终端着色
性能优化建议
对于大文件对比(>10MB),建议:
- 使用
git diff替代原生diff(基于哈希算法加速) - 限制对比范围(如
diff -u --lines=100) - 采用二进制对比工具(如
hexdump+cmp组合)
Java技术:Elasticsearch数据去重查询实践
在分布式系统中,数据去重是常见需求。以日志分析场景为例,需从海量事件中提取最新记录。Elasticsearch的CollapseBuilder提供高效解决方案。
基础去重查询
通过field collapse实现单字段去重,核心代码示例:
SearchRequest request = new SearchRequest("logs-*");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();// 构建CollapseBuilderCollapseBuilder collapseBuilder = new CollapseBuilder("user_id"); // 按用户ID去重sourceBuilder.collapse(collapseBuilder);// 添加排序(确保获取最新记录)sourceBuilder.sort("timestamp", SortOrder.DESC);sourceBuilder.size(1); // 每组仅返回1条request.source(sourceBuilder);SearchResponse response = client.search(request, RequestOptions.DEFAULT);
执行逻辑:
- 按
user_id分组 - 每组按
timestamp降序排序 - 仅保留每组首条记录(即最新记录)
嵌套聚合查询
当需处理多级关联数据时,可采用terms聚合+top_hits子聚合:
SearchRequest request = new SearchRequest("orders");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();// 一级聚合:按客户ID分组TermsAggregationBuilder customerAgg = AggregationBuilders.terms("by_customer").field("customer_id");// 二级聚合:每组内获取最新订单TopHitsAggregationBuilder latestOrderAgg = AggregationBuilders.topHits("latest_order").size(1).sort("order_date", SortOrder.DESC).fetchSource(new String[]{"order_id", "amount"}, null); // 仅返回指定字段customerAgg.subAggregation(latestOrderAgg);sourceBuilder.aggregation(customerAgg);request.source(sourceBuilder);SearchResponse response = client.search(request, RequestOptions.DEFAULT);
性能优化技巧:
- 限制聚合层级(建议不超过3级)
- 使用
docvalue_fields替代_source(减少I/O开销) - 对高频查询字段启用
fielddata缓存
实时性保障方案
对于高并发写入场景,可通过以下方式确保数据一致性:
- 近实时搜索:设置
refresh_interval=1s(默认1s) - 索引分片优化:根据数据量配置合理分片数(建议单分片不超过50GB)
- 查询重试机制:捕获
SearchPhaseExecutionException并实现指数退避重试
跨技术栈整合实践
在实际项目中,常需结合Shell脚本与Java技术实现端到端解决方案。例如日志处理流水线:
- 数据采集层:通过Shell脚本监控文件变更(
inotifywait+rsync) - 预处理层:使用
awk/sed清洗数据格式 - 存储层:通过Java客户端批量写入Elasticsearch
- 查询层:构建CollapseBuilder实现高效去重
完整示例:日志处理脚本
#!/bin/bash# 监控日志目录变化inotifywait -m -r -e modify /var/log/app/ | while read path action file; do# 实时过滤有效日志grep -E 'ERROR|WARN' "$path$file" | awk '{print $1,$3,$5}' > processed.log# 调用Java程序导入ESjava -jar log-importer.jar --input processed.log --index app-errorsdone
总结与最佳实践
-
Shell脚本选择:
- 小文件对比:优先使用
diff原生命令 - 大文件处理:结合
git diff或专用工具(如meld) - 自动化场景:封装为函数并添加错误处理
- 小文件对比:优先使用
-
Elasticsearch查询优化:
- 合理设置
size参数(避免全量扫描) - 对高频查询字段建立索引
- 使用
profileAPI分析查询性能瓶颈
- 合理设置
-
跨技术协作:
- 明确技术栈边界(如Shell负责本地处理,Java负责分布式计算)
- 通过标准格式(JSON/CSV)实现数据交换
- 建立统一的日志规范与字段命名标准
通过本文介绍的方案,开发者可构建从文件级对比到分布式数据查询的完整技术体系,满足从单机运维到大规模数据处理的多场景需求。实际项目中,建议根据数据规模、实时性要求等因素综合选择技术方案,并通过压力测试验证系统承载能力。