Bash脚本高效处理大体积两列文件 过滤第一列空格后冗余内容
问题描述
- 输入文件为制表符
\t分隔的两列文本,存在脏数据:部分行的第一列混入空格\s分隔的多余值,原始数据样例:
A\t1 B\t2 C\sx\t3 D\t4 E\sy\t5
- 处理目标:丢弃第一列中空格后的所有多余内容,输出标准两列格式,预期结果:
A\t1 B\t2 C\t3 D\t4 E\t5
例:脏行C\sx\t3需删除第一列空格后的x,输出C\t3。
- 约束条件:文件共530万行,需避免逐行循环的低效率处理方式。
原有方案的问题
之前尝试的切割拼接方案运行异常,代码如下:
col1=(cut -d$'\t' -f1 $file | cut -d' ' -f1) col2=(cut -d$'\t' -f1 $file) myArr=() for((idx=0;idx<${#col1[@]};idx++));do echo "@{col1[$idx]} @{col2[$idx]}" # 后续追加到myArr的逻辑 done
运行后col2内容整体拼接到col1列表后,输出为A B C D E 1 2 3 4 5,不符合预期。
高效解决方案
大文件处理优先选用流处理工具,无需加载全量数据到内存,处理速度远高于bash循环,530万行数据通常数秒即可完成。
推荐方案:awk单命令处理
直接通过awk完成字段切割、清洗、拼接全流程,命令如下:
awk -F '\t' '{split($1, arr, " "); print arr[1]"\t"$2}' 输入文件路径 > 输出文件路径
逻辑说明:
-F '\t'指定按制表符分割每行字段split($1, arr, " ")对第一列再按空格分割,结果存入arr数组,arr[1]就是第一列空格前的有效值- 最后用制表符拼接有效值和原第二列,直接输出
原有bash脚本错误说明
如果要使用bash数组逻辑(大文件场景极不推荐),原有代码存在3个核心错误:
- 命令执行结果赋值给数组需要用
$()捕获,原写法不会执行cut命令 - 提取第二列的cut命令参数错误,应为
-f2而非-f1 - 数组取值语法错误,应为
${变量名}而非@{变量名},且输出拼接需用制表符而非空格
修正后的参考代码(仅做语法演示,禁止用于大文件处理):
col1=($(cut -d$'\t' -f1 "$file" | cut -d' ' -f1)) col2=($(cut -d$'\t' -f2 "$file")) for((idx=0;idx<${#col1[@]};idx++));do printf "%s\t%s\n" "${col1[$idx]}" "${col2[$idx]}" done
警告:bash数组方案会将全量数据加载到内存,530万行会占用极高内存,且shell循环处理速度比awk慢百倍以上,请勿在生产环境使用。
内容的提问来源于stack exchange,提问作者Rajesh M
相关产品推荐
相关产品推荐

