大文本空条目补全优化:替换低效Bash脚本的高效方案
高效补全超大文本缺失条目的解决方案
问题描述
有一个超大文本文件,内容按「区块」划分:每个区块的首行包含完整条目,后续行缺失前两个字段,需要用该区块首行的前两个字段补全缺失行,直到遇到新的完整首行。现有Bash逐行脚本因频繁调用外部工具(grep、sed),处理速度极慢(耗时数小时),需要更高效的实现方案。
注意:输入并非规范CSV,首行以{开头,每行以]结尾,无法直接用CSV解析库处理。
输入示例
{"Initial line with more information like headers, unimportant, really only one line" "Alpha","OldTheme","Some more text"] "","","Another rest text"] "","","Yet another text"] "Yadda","NewTheme","Crazy Text"] "","","More crazy text"]
预期结果
"Alpha","OldTheme","Some more text"] "Alpha","OldTheme","Another rest text"] "Alpha","OldTheme","Yet another text"] "Yadda","NewTheme","Crazy Text"] "Yadda","NewTheme","More crazy text"]
现有脚本低效原因
现有Bash脚本逐行处理时,每一行都多次调用grep、sed等外部命令,每次调用都会启动新进程,大量进程创建/销毁的开销导致整体处理速度极慢。
高效解决方案
方案1:使用Awk脚本(推荐)
Awk是单进程处理工具,无需频繁启动外部命令,处理大文件速度远快于逐行调用外部工具的Bash脚本。
实现脚本:
#!/usr/bin/awk -f # 跳过首行(以{开头的行) NR == 1 { next } # 分割字段,分隔符为",",适配带引号的格式 BEGIN { FS = "\"\",\"\"" } # 处理完整首行:提取并保存前两个字段的前缀 $1 !~ /^"$/ { match($0, /^"[^"]+","[^"]+"/) prefix = substr($0, RSTART, RLENGTH) print $0 next } # 处理缺失行:用保存的前缀补全开头的空字段 { print prefix "," substr($0, 4) }
使用方式:
将脚本保存为fill_missing.awk,执行:
awk -f fill_missing.awk inputfile > outputfile
方案2:使用Sed脚本
Sed是单进程流处理工具,适合文本替换场景,同样能避免频繁启动外部进程的开销。
实现脚本:
#!/usr/bin/sed -f # 跳过首行 1d # 遇到完整首行时,提取前两个字段保存到暂存区,并输出原行 /^"[^"]","[^"]"/ { s/^\("\([^"]\+\)","\([^"]\+"\)\).*/\1\2/ h g p d } # 处理缺失行:用暂存区的前缀替换开头的空字段 /^"",""/ { G s/^"",""\(.*\)\n\(.*\)/\2,\1/ }
使用方式:
保存为fill_missing.sed,执行:
sed -f fill_missing.sed inputfile > outputfile
效果说明
上述两种方案均为单进程流处理,无需逐行调用外部工具,处理大文件的速度会比原Bash脚本提升数十倍甚至上百倍,能大幅缩短处理时间。
内容的提问来源于stack exchange,提问作者Stefan M
相关产品推荐
相关产品推荐

