我有一个带有一堆序列号的文本文件,它们应该有 16 个字符长。但有些记录已损坏,长度为 13 个字符。我想在每条长度为 13 个字符的记录的开头添加 3 个零。
注意:序列号不是从行首开始的,它们都从每行的第 15 列开始。
我的文件目前如下所示:
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: :
这是我为获取缩短的记录而编写的代码:
#!/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
txt 文件有超过 50,000 条记录,所以我无法手动更改它们。
这个sed
单行应该可以完成这项工作:
sed 's/^(.{14})([0-9]{13}[^0-9])/10002/' file
这假定序列号仅由十进制数字组成,并相信它们都从行的第 15 个字符开始。
或者,一个awk
解决方案:
awk 'BEGIN { FS=OFS=":" } length($6) == 13 { $6 = "000" $6 } 1 ' file
这只检查第六个字段的长度是否为 13,并信任第六个字段是序列号字段。
一个awk
想法,它取代了OP的所有当前代码:
awk '
BEGIN { FS=OFS=":" } # set input/output field delimiter to ":"
length($6)<16 { $6=sprintf("%016d",$6) } # if length of 6th field < 16 then left-pad the field with 0's to length of 16
1 # print current line
' file.txt
这将生成:
1:6822:26: :A:0000000000999993:DIS:14516E : :01: : : ::0529483733710: : :
1:6822:26: :A:0000000000999994:MAT:13L324 : :01: : : :: : : :
1:6822:26: :A:0000000000999995:CAT:P13WFB : :01: : : ::0529483697940: : :
1:6822:26: :3:0000000000170891: :AZDG-2 :0000003999:01:0000000000: : :: : : :
1:6822:26: :3:0000000000170892: :AZDG-3 :0000003999:01:0000000000: : :: : : :
1:6822:26: :3:0000000000170893: :AZDG-4 :0000003999:01:0000000000: : :: : : :
我冒昧:
地
$ awk '{if(length($2)<19){$2=gensub(/^(:.:)/,"\1000","1",$2)":"}}1' file.txt
1:6822:26: :A:0000000000999993: :DIS:14516E : :01: : : ::0529483733710: : :
1:6822:26: :A:0000000000999994: :MAT:13L324 : :01: : : :: : : :
1:6822:26: :A:0000000000999995: :CAT:P13WFB : :01: : : ::0529483697940: : :
1:6822:26: :3:0000000000170891: :AZDG-2 :0000003999:01:0000000000: : :: : : :
1:6822:26: :3:0000000000170892: :AZDG-3 :0000003999:01:0000000000: : :: : : :
1:6822:26: :3:0000000000170893: :AZDG-4 :0000003999:01:0000000000: : :: : : :
如果这不是您想要的,请使用以下内容:awk '{if(length($2)<19){$2=gensub(/^(:.:)/,"\1000","1",$2)}}1' file.txt
另一种选择
awk -v{O,}FS=: '{$6=gensub(" ", "0", "g", sprintf("%16s", gensub(" ", "", "g", $6)))}1'
结果
1:6822:26: :A:0000000000999993:DIS:14516E : :01: : : ::0529483733710: : :
1:6822:26: :A:0000000000999994:MAT:13L324 : :01: : : :: : : :
1:6822:26: :A:0000000000999995:CAT:P13WFB : :01: : : ::0529483697940: : :
1:6822:26: :3:0000000000170891: :AZDG-2 :0000003999:01:0000000000: : :: : : :
1:6822:26: :3:0000000000170892: :AZDG-3 :0000003999:01:0000000000: : :: : : :
1:6822:26: :3:0000000000170893: :AZDG-4 :0000003999:01:0000000000: : :: : : :