Friday, October 28, 2022

[SOLVED] How can I append a string on a specific column on the lines that match a condition on a txt file using shell scripting?

Issue

I have a text file with a bunch of serial numbers and they're supposed to be 16 characters long. But some of the records were damaged and are 13 characters long. I want to add 3 zeros at the beginning of every record that has 13 characters long.

Note: The serial numbers doesn't start at the beginning of the line, they all start at the column 15 of every line.

My file currently looks like this:

1:6822:26: :A:0000000999993: :DIS:14516E : :01: : : ::0529483733710: : :
1:6822:26: :A:0000000999994: :MAT:13L324 : :01: : : :: : : :
1:6822:26: :A:0000000999995: :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: : :: : : :

And the output should be:

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: : :: : : :

This is the code I made to get the records that are shortened:

    #!/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

The txt file has more than 50,000 records so I can't change them manually.


Solution

This sed one-liner should do the job:

sed 's/^\(.\{14\}\)\([0-9]\{13\}[^0-9]\)/\1000\2/' file

This assumes serial numbers consist of decimal digits only and trusts that they all start at the column 15 of every line.

Or, an awk solution:

awk 'BEGIN { FS=OFS=":" } length($6) == 13 { $6 = "000" $6 } 1 ' file

This one only checks if the length of the sixth field is 13 and trusts that sixth field is the serial number field.



Answered By - M. Nejat Aydin
Answer Checked By - Senaida (WPSolving Volunteer)