Shell脚本批量修复指定列13位序列号:前缀补3个0
批量修复指定位置的短序列号
我有一个包含5万多条记录的文本文件,其中序列号从每行第15列开始,正常长度为16字符,但部分损坏成了13字符。需要给所有13位的序列号开头补3个0,使其恢复为16位长度。
原文件示例
1:CCCC:CC: :C:0000000999993: :CCC: : 1:CCCC:CC: :C:0000000999994: :CCC: : 1:CCCC:CC: :C:0000000999995: :CCC: : 1:CCCC:CC: :C:0000000000170891: :CCC: : 1:CCCC:CC: :C:0000000000170892: :CCC: : 1:CCCC:CC: :C:0000000000170893: :CCC: :
期望输出
1:CCCC:CC: :C:0000000000999993: :CCC: : 1:CCCC:CC: :C:0000000000999994: :CCC: : 1:CCCC:CC: :C:0000000000999995: :CCC: : 1:CCCC:CC: :C:0000000000170891: :CCC: : 1:CCCC:CC: :C:0000000000170892: :CCC: : 1:CCCC:CC: :C:0000000000170893: :CCC: :
我之前写了一段bash脚本只能筛选出短记录,但无法直接修改原文件:
#!/bin/bash i=1 for OUTPUT in $(cut -c15-30 file.txt) do if [[ ${#OUTPUT} == 13 ]] then echo $OUTPUT echo $i i=$((i+1)) fi done
高效解决方案
针对大文件,推荐用awk或sed处理,它们都是流式文本工具,内存占用低、处理速度快,适合5万+行的场景。
方法1:用awk按列位置处理
这个方法不依赖字段分隔符,严格按照第15列的起始位置处理,兼容性更强:
awk '{ # 提取前14个字符作为前缀 head = substr($0, 1, 14) # 提取从第15位开始的剩余内容 tail = substr($0, 15) # 匹配开头的数字序列(即序列号) match(tail, /^[0-9]+/) serial = substr(tail, RSTART, RLENGTH) # 如果序列号长度是13,补3个0 if (length(serial) == 13) { new_tail = "000" serial substr(tail, RSTART+RLENGTH) } else { new_tail = tail } # 拼接并输出完整行 print head new_tail }' file.txt > fixed_file.txt
方法2:用sed简洁处理(适用于纯数字序列号)
如果确认序列号是纯数字,且后面紧跟非数字字符(比如示例中的:),可以用更简洁的sed命令:
sed -E 's/^(.{14})([0-9]{13})([^0-9])/\1000\2\3/' file.txt > fixed_file.txt
命令解释:
^(.{14}):匹配前14个字符并保存([0-9]{13}):匹配接下来的13位数字(短序列号)并保存([^0-9]):匹配序列号后的第一个非数字字符并保存- 替换为
\1000\2\3:在前14个字符后添加000,再拼接原序列号和后续内容
原脚本的问题说明
你之前的bash脚本存在两个明显问题:
- 语法错误:
for OUTPUT in $*(cut ...)应该是$(cut ...),否则会把cut当作参数传递给当前脚本的参数列表 - 效率低且功能有限:循环遍历cut的输出时,若内容包含空格会被拆分,导致判断错误;而且只能筛选无法修改原文件,不适合大规模处理。
内容的提问来源于stack exchange,提问作者Luis Meléndez
相关产品推荐
相关产品推荐

