Bash脚本数组赋值异常及rt_facts区间匹配效率优化问题
问题1 数组赋值失效原因及解决
原因:你使用的cat rt_facts | while IFS=" " read -r lineStr结构中,管道符后的while循环运行在独立的子shell中,子shell内对arr数组的所有修改仅在子进程内有效,不会同步到父shell的数组变量,因此循环结束后父shell只能看到循环外赋值的arr[0]。
解决方法:把管道输入改为文件重定向,让while循环运行在当前shell进程,修改方式如下:
将原有代码段
cat rt_facts | while IFS=" " read -r lineStr do # 原有循环逻辑 done
替换为
while IFS=" " read -r lineStr do # 原有循环逻辑不变 done < rt_facts
修改后数组赋值即可在全局生效。
问题2 区间匹配高效优化方案
原有实现每次处理一个l_num都要重复读取rt_facts文件、反复调用cut命令,性能开销大,可从两个维度优化:
- 一次性预加载rt_facts的所有区间到内存,避免重复读文件
- 用bash原生参数扩展代替cut命令,减少子进程创建开销
优化逻辑:
- 脚本启动时先读一遍rt_facts,把每个区间的rt_h、rt_f、对应索引i分别存入三个数组,后续所有l_num直接遍历内存数组匹配即可
- 提取rt_h、rt_f时用
${var%%:*}直接截断冒号后的内容,不需要调用cut
如果rt_facts的区间本身是有序的,还可以进一步用二分查找减少匹配次数,数据量不大的情况下预加载内存+原生参数扩展的优化已经足够。
优化后完整脚本示例
#!/bin/bash # 预加载rt_facts区间信息到内存 declare -a rt_h_arr rt_f_arr idx_arr fact_cnt=0 while IFS=' ' read -r -a line; do idx_arr[$fact_cnt]=${line[1]} rt_h_arr[$fact_cnt]=${line[2]%%:*} rt_f_arr[$fact_cnt]=${line[3]%%:*} ((fact_cnt++)) done < rt_facts cols=$((fact_cnt + 1)) declare -a arr arr[0]="4046580009982686 05072021 24692161126100379438583 44442" # 遍历所有匹配的l_num while IFS=' ' read -r l_num rest; do [[ $rest != "${arr[0]}" ]] && continue echo "l_num $l_num" for ((i=0; i<fact_cnt; i++)); do rt_h=${rt_h_arr[$i]} rt_f=${rt_f_arr[$i]} if (( l_num > rt_h && l_num < rt_f )); then echo "rt_h rt_f $rt_h $rt_f" idx=${idx_arr[$i]} echo "i $idx" if [[ -z ${arr[$idx]} ]]; then echo "empty" arr[$idx]=0 fi ((arr[$idx]++)) echo "arr[$idx] ${arr[$idx]}" break fi done echo done < filtered_file echo ${arr[@]} echo ${arr[*]} echo ${arr[2]}
内容的提问来源于stack exchange,提问作者Elcappoo
相关产品推荐
相关产品推荐

