如何用Shell脚本转换大体积单行XML为多行 解决SED处理2G以上文件失效问题
故障原因
原有sed 's/></>\n</g'命令处理2GB以上单行XML失败,核心原因是sed默认以换行符作为行分隔单位,处理无换行的超长单行时,会尝试将整行内容全部加载到内存缓冲区做正则匹配,一旦内容长度超过sed内置行缓冲区上限、或者触发系统内存阈值,就会直接崩溃,调优sed参数无法从根本上解决这个逻辑问题。
稳定处理方案
以下方案均为流处理逻辑,不会将全量文件加载到内存,内存占用固定在KB~MB级,支持TB级超大文件处理,转换逻辑和原有sed命令完全一致:仅在相邻的>和<之间插入换行,不会修改XML文本节点、属性内的内容。
方案1:Perl 流处理(推荐,兼容所有场景,速度快)
绝大多数Linux/Unix发行版默认预装Perl,通过分块读取+边界留种的方式避免跨块匹配遗漏,完全复刻原sed的替换逻辑,命令如下:
perl -e ' $/ = \8192; $tail = ""; while (sysread(STDIN, $buf, 8192)) { $buf = $tail . $buf; $tail = substr($buf, -1, 1, ""); $buf =~ s/></>\n</g; print $buf; } print $tail; ' < 你的输入文件.xml > 转换后输出.xml
单行快速执行版本:
perl -e '$/=\8192;$t="";while(sysread(STDIN,$b,8192)){$b=$t.$b;$t=substr($b,-1,1,"");$b=~s/></>\n</g;print $b}print $t' < input.xml > output.xml
方案2:mawk 高速处理(适合无文本节点的纯标签XML)
如果你的XML文件没有文本内容、所有尖括号都是标签组成部分,可以用mawk(比普通awk速度快3-5倍)自定义分隔符处理,内存占用更低,速度更快:
# debian/ubuntu系可直接执行apt install mawk安装 mawk 'BEGIN{RS=">";ORS=">\n"} {printf "%s",$0}' input.xml | sed '$ s/>$//' > output.xml
注意:该方案会在所有
>后插入换行,如果XML存在<tag>文本内容</tag>这类带文本节点的结构,会错误拆分文本内容,仅适合纯标签结构的XML。
注意事项
- 严禁直接将输出重定向到原输入文件,会直接清空原文件内容,必须先输出到独立的临时文件,校验无误后再替换原文件
- 转换完成后可通过
head -n 10 output.xml、tail -n 10 output.xml抽查首尾格式,确认没有截断、错换问题 - 如需保留原文件权限,转换完成后执行
cp --attributes-only input.xml output.xml同步权限属性即可
内容的提问来源于stack exchange,提问作者mayank agrawal
相关产品推荐
相关产品推荐

