1

I have a .pdb file that looks like this:

ATOM      1  N   PRO  137     -17.579 -25.693 -70.648
ATOM      2  CA  PRO  137     -18.871 -26.246 -70.218
ATOM      3  C   PRO  137     -19.596 -25.304 -69.246
ATOM      4  O   PRO  137     -20.765 -24.998 -69.484
ATOM      5  CB  PRO  137     -18.481 -27.564 -69.543
ATOM      6  CG  PRO  137     -17.101 -27.876 -70.074
ATOM      7  CD  PRO  137     -16.451 -26.550 -70.252
ATOM      8  N   SER  138     -18.911 -24.902 -68.166
ATOM      9  CA  SER  138     -19.217 -23.716 -67.352
ATOM     10  C   SER  138     -20.313 -23.914 -66.299
ATOM     11  O   SER  138     -21.436 -24.315 -66.621
ATOM     12  CB  SER  138     -19.572 -22.537 -68.260
ATOM     13  OG  SER  138     -19.975 -21.410 -67.504
ATOM     14  N   LEU  139     -20.005 -23.580 -65.038
ATOM     15  CA  LEU  139     -20.898 -23.917 -63.925
ATOM     16  C   LEU  139     -22.188 -23.123 -63.970
ATOM     17  O   LEU  139     -23.279 -23.682 -63.782
ATOM     18  CB  LEU  139     -20.188 -23.699 -62.583
ATOM     19  CG  LEU  139     -19.627 -24.970 -61.946
ATOM     20  CD1 LEU  139     -18.755 -24.666 -60.742
ATOM     21  CD2 LEU  139     -20.728 -25.961 -61.590
ATOM     22  N   GLU  140     -22.082 -21.810 -64.173
ATOM     23  CA  GLU  140     -23.280 -21.015 -64.387
ATOM     24  C   GLU  140     -24.115 -21.597 -65.524
ATOM     25  O   GLU  140     -25.351 -21.623 -65.454
ATOM     26  CB  GLU  140     -22.905 -19.560 -64.677
ATOM     27  CG  GLU  140     -21.960 -18.903 -63.663
ATOM     28  CD  GLU  140     -20.499 -19.211 -63.923
ATOM     29  OE1 GLU  140     -19.671 -18.277 -63.859
ATOM     30  OE2 GLU  140     -20.180 -20.384 -64.201

I want to match column with three numbers (137 etc) and to replace these numbers with 1..2..3. So I would like to replace 137 with 1, 138 with 2 etc. I cannot simply match the number because the file is big and at the and of the file numbers are repeating.

Preferably what I am expecting to get is something like this:

ATOM      1  N   PRO    1     -17.579 -25.693 -70.648
ATOM      2  CA  PRO    1     -18.871 -26.246 -70.218
ATOM      3  C   PRO    1     -19.596 -25.304 -69.246
ATOM      4  O   PRO    1     -20.765 -24.998 -69.484
ATOM      5  CB  PRO    1     -18.481 -27.564 -69.543
ATOM      6  CG  PRO    1     -17.101 -27.876 -70.074
ATOM      7  CD  PRO    2     -16.451 -26.550 -70.252
ATOM      8  N   SER    2     -18.911 -24.902 -68.166
ATOM      9  CA  SER    2     -19.217 -23.716 -67.352
ATOM     10  C   SER    2     -20.313 -23.914 -66.299
ATOM     11  O   SER    2     -21.436 -24.315 -66.621
ATOM     12  CB  SER    2     -19.572 -22.537 -68.260
ATOM     13  OG  SER    2     -19.975 -21.410 -67.504
.
.
.
.
ATOM     14  N   LEU   39     -20.005 -23.580 -65.038
ATOM     15  CA  LEU   39     -20.898 -23.917 -63.925
ATOM     16  C   LEU   39     -22.188 -23.123 -63.970
ATOM     17  O   LEU   39     -23.279 -23.682 -63.782
ATOM     18  CB  LEU   39     -20.188 -23.699 -62.583
ATOM     19  CG  LEU   39     -19.627 -24.970 -61.946
ATOM     20  CD1 LEU   39     -18.755 -24.666 -60.742
ATOM     21  CD2 LEU   39     -20.728 -25.961 -61.590

What may be of help is that for each three letters ID (PRO, SER, LEU) there is one specific number.

How can I achieve this in Bash?

2
  • Is there any reason why 139 was changed to be 39 instead of 3 (e.g. lines 14->21)
    – Yaron
    Oct 25 '18 at 6:53
  • 1
    Thanks for Your question. 139 and 39 have nothing in common. I just wanted to point out that the file is big and that it will go to 39 or even more numbers, probably up to ~100. Instead of ' 39' there can be either ' 3' or ' 15' or '121'.
    – djordje
    Oct 25 '18 at 6:58
3

The following awk script will kept track of all number in the 5th field and will substitute them with a counting number:

awk '!a[$5]{a[$5]=++c}{$5=a[$5]}1' file | column -t

The array a stores the counting number. This one is increased when a new number in the 5th field is seen, then it is assigned to that field.

If you want to increase the counting number every time the value of the 5th field is changed, use this:

awk 'o!=$5{++c}{o=$5;$5=c}1' file | column -t

The variable o keeps the 5th field value of the past line and the counter c is increase whenever the variable o changes.

column -t command formats the output into columns.

3
  • Hey, this is a good and clever way but the problem I am encountering is that we shouldn't match the number because on lets say 5000th line I have again number 137, 138 etc in my input file. So in my output I have numbers 1 to 489 and then in the middle of the input file (~5000th line) when I have number 137, 138 it starts from the beginning again to ad 1, 2, 3..
    – djordje
    Oct 25 '18 at 7:23
  • I should try to match the three letters before the number and then say: Until the three number letter (XXX, we can match either letter because letters are also repeating everywhere in the file) is the same different row (for example PRO) print 1, when it encounters new XXX print 2, again new XXX print 3 etc
    – djordje
    Oct 25 '18 at 7:26
  • @djordje answer updated
    – oliv
    Oct 25 '18 at 7:48
1

If I understand your question correctly, you could use this:

perl -ane '$F[4]-=136; print join("\t",@F);' input.txt > output.txt

This command will read your input file line wise, subtract 136 from the number in the fifth column and then write the results to the output file. So 137 will be converted to 1, 138 to 2 and so on.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.