数组排序与去重:linux-tutorial Shell数据处理技巧
在Linux系统管理和数据处理中,数组(Array)是Shell脚本存储和操作批量数据的重要工具。日常运维中,我们经常需要对服务器监控指标、日志条目、用户列表等数据进行排序和去重处理。本文将结合linux-tutorial项目中的实战脚本,详细讲解如何使用Shell数组配合sort、uniq、awk等工具实现高效数据清洗,解决重复数据统计、性能指标排序等高频需求。
数组基础:从定义到访问
Shell数组(Array)是一组有序数据的集合,支持存储数字、字符串甚至包含空格的文本。在linux-tutorial项目的数组使用示例脚本中,展示了多种数组操作方法:
定义与初始化
# 索引初始化(支持非连续索引)
nums=( [2]=2 [0]=0 [1]=1 )
# 直接赋值(自动分配索引)
colors=( red yellow "dark blue" ) # 带空格的元素需用引号包裹
元素访问
echo ${nums[1]} # 访问单个元素,输出: 1
echo ${colors[@]} # 访问所有元素,输出: red yellow dark blue
echo ${#colors[*]} # 获取数组长度,输出: 3
数组在日志分析场景中应用广泛,例如存储服务器CPU使用率采样数据:cpu_usages=(3.2 1.8 5.6 1.8 4.1),后续可通过排序快速定位性能峰值。
排序实现:系统工具与纯Shell方案
借助sort命令的外部排序
最常用的数组排序方法是将数组元素通过管道传递给sort命令。sort支持数值排序(-n)、逆序(-r)、去重(-u)等参数,结合tr和xargs工具可实现数组与文本流的转换:
# 定义测试数组(含重复值和非数值)
data=( apple 3 banana 1 2 apple )
# 字符串排序(默认字典序)
sorted_str=($(printf "%s\n" "${data[@]}" | sort))
echo "字符串排序: ${sorted_str[@]}" # 输出: 1 2 3 apple apple banana
# 数值排序(需指定-n参数)
nums=(5 2 8 2 9)
sorted_num=($(printf "%s\n" "${nums[@]}" | sort -n))
echo "升序排序: ${sorted_num[@]}" # 输出: 2 2 5 8 9
echo "降序排序: $(printf "%s\n" "${nums[@]}" | sort -nr)" # 输出: 9 8 5 2 2
纯Shell的冒泡排序实现
对于小型数组或无外部命令依赖场景,可使用嵌套循环实现冒泡排序。参考项目中逻辑控制脚本的循环结构,实现纯Shell排序:
#!/bin/bash
# 冒泡排序实现(源自linux-tutorial逻辑控制模块)
arr=(64 34 25 12 22 11 90)
n=${#arr[@]}
# 外层循环控制轮次
for ((i=0; i < n; i++)); do
# 内层循环比较相邻元素
for ((j=0; j < n-i-1; j++)); do
# 数值比较(需用双括号语法)
if (( arr[j] > arr[j+1] )); then
# 交换元素
temp=${arr[j]}
arr[j]=${arr[j+1]}
arr[j+1]=$temp
fi
done
done
echo "排序结果: ${arr[@]}" # 输出: 11 12 22 25 34 64 90
性能提示:纯Shell排序适合处理1000元素以内的数组,大数据量建议使用
sort -n,其底层C实现效率更高。
去重技巧:从简单到高级
使用uniq命令快速去重
uniq命令可移除连续重复行,常与sort配合使用(先排序使重复值相邻):
# 数组去重(需先排序)
fruits=( apple banana apple orange banana grape )
unique_fruits=($(printf "%s\n" "${fruits[@]}" | sort | uniq))
echo "去重结果: ${unique_fruits[@]}" # 输出: apple banana grape orange
# 统计重复次数
printf "%s\n" "${fruits[@]}" | sort | uniq -c
# 输出:
# 2 apple
# 2 banana
# 1 grape
# 1 orange
关联数组去重(保留原始顺序)
当需要保持元素插入顺序时,可使用Bash 4.0+支持的关联数组(类似哈希表)实现去重。项目中数组使用示例展示了关联数组的基本用法:
#!/bin/bash
declare -A seen # 声明关联数组存储已见过的元素
original=( apple banana apple orange banana grape )
result=()
for item in "${original[@]}"; do
if [[ -z "${seen[$item]}" ]]; then
seen[$item]=1 # 标记为已见过
result+=("$item") # 添加到结果数组
fi
done
echo "有序去重结果: ${result[@]}" # 输出: apple banana orange grape
该方法在日志事件去重场景中特别有用,例如保留用户操作序列的原始顺序同时去除重复点击记录。
实战案例:服务器监控数据处理
结合linux-tutorial项目中的系统快照报告脚本,我们实现一个服务器CPU使用率分析工具,功能包括:
- 采集5次CPU使用率(间隔1秒)
- 去除异常值(低于1%或高于99%)
- 排序后显示TOP 3峰值
#!/bin/bash
# 服务器CPU使用率分析工具
# 依赖: codes/shell/进阶脚本/系统快照报告.sh中的监控逻辑
cpu_samples=()
# 采集5次CPU使用率(使用vmstat工具)
for ((i=0; i<5; i++)); do
usage=$(vmstat 1 2 | tail -1 | awk '{print $13 + $14}')
cpu_samples+=("$usage")
sleep 1
done
# 数据清洗:过滤异常值并排序
filtered=($(printf "%.1f\n" "${cpu_samples[@]}" |
awk '$1 >= 1 && $1 <= 99' | # 过滤异常值
sort -nr)) # 降序排序
# 输出结果
echo "原始采样: ${cpu_samples[@]}%"
echo "有效峰值: ${filtered[@]}%"
echo "TOP 3峰值: ${filtered[@]:0:3}%"
运行效果:
原始采样: 2.3 1.8 102.5 3.5 2.1%
有效峰值: 3.5 2.3 2.1 1.8%
TOP 3峰值: 3.5 2.3 2.1%
高级技巧:awk数组与多字段排序
awk内置数组实现高效去重
awk工具提供了内置关联数组,特别适合处理结构化数据。项目中gawk使用示例展示了数组在数据聚合中的应用:
# 统计日志中各IP的访问次数(源自access.log)
awk '{
ips[$1]++ # 以IP为键累加计数
}
END {
# 遍历数组输出结果
for (ip in ips) {
print ip, ips[ip]
}
}' access.log | sort -k2nr # 按访问次数降序排序
多字段排序实战
处理CSV格式数据时,可指定排序字段。例如对进程列表按内存使用率和PID排序:
# 按内存使用率(第4列)降序,PID(第2列)升序排序
ps aux | awk 'NR>1 {print $2, $4, $11}' | sort -k2nr -k1n
总结与扩展阅读
本文介绍的数组处理技巧已整合到linux-tutorial项目的多个脚本中:
- 基础操作:数组使用示例.sh
- 排序算法:while循环示例.sh
- 系统监控:系统快照报告.sh
- 文本处理:gawk使用模式.sh
进阶学习建议:
- 掌握
sort命令的高级选项:-t指定分隔符、-k指定排序字段 - 学习
awk数组的多维应用:stats[date][ip]++实现按日期和IP的二维统计 - 结合项目中sed编辑器脚本实现复杂文本转换
通过这些工具的组合使用,运维人员可高效处理日志分析、性能监控、用户行为统计等日常任务,提升Linux系统管理效率。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



