Skip to content
Advertisement

How to use python to replace a value in a field in a text file

I have a file that looks like this:

;
[ atomtypes ]
  opls_BZCG BCG1    78.113999   0.000   A   2.9310E-01  1.9173E-01
[ moleculetype ]
; Name      nrexcl
BZCG        1
[ atoms ]
;   nr  type    resnr   residue atom    cgnr    charge  mass
    1   opls_BZCG   1       BZCG    BCG1        1       0       78.113999

I am trying to use python to change the values in the second last and last field under the [ atomtypes ] title. The deal is that I am running a code which iteratively updates this file, so I specifically want that field to be targeted, not the regular expression “2.931E-01” or “1.9173E-01”. I know we can use things like awk, but I was wondering if this is possible from python itself.

This is what I am doing so far:

flag = 0
with open("file.itp") as f: 
  for line in f:
     iterable = line.strip().split()
        if flag:
            line.strip().split()[5] = sigma 
            line.strip().split()[6]) = eps 
            print("epsilon is {} and sigma is {}".format(eps, sigma))
        if "atomtypes" in iterable:
            flag = 1
        else:
            flag = 0

    f.close()

I am changing the value in python, but I am not able to send that change to the file itself. How do I pull this off?

Any advice you have would be appreciated!

Advertisement

Answer

Use enumerate on lines so we can access current line and next line

Code

def update_line(filenm, eps, sigma):
    with open(filenm, 'r') as fin:
        lines = fin.readlines()
        
        for idx, line in enumerate(lines):
            if "atomtypes" in line:
                # Current line has marker, so change next line (i.e. index idx + 1)
                #   Split next line into fields 
                #   split from end so so only have three fields, namely:
                #    1) everything before next to last field, 
                #    2) next to last field, 
                #    3) last field)
                arr = lines[idx+1].rsplit(' ', maxsplit = 3)
                arr[-3], arr[-1] = f"{eps:e}", f"{sigma:e}"
                lines[idx+1] = ' '.join(arr) + "n"  # last_val dropped the 'n' so add back
                break
        
    with open(filenm, 'w') as fout:
        # Updated lines placed back into file
        fout.writelines(lines)
    

Test

update_line('test.txt', 4.573133E-02, 8.2737123E-01)

File test.txt prior:

;
[ atomtypes ]
  opls_BZCG BCG1    78.113999   0.000   A   2.9310E-01  1.9173E-01
[ moleculetype ]
; Name      nrexcl
BZCG        1
[ atoms ]
;   nr  type    resnr   residue atom    cgnr    charge  mass
    1   opls_BZCG   1       BZCG    BCG1        1       0       78.113999

File test.txt after

;
[ atomtypes ]
  opls_BZCG BCG1    78.113999   0.000   A   4.573133e-02  8.273712e-01
[ moleculetype ]
; Name      nrexcl
BZCG        1
[ atoms ]
;   nr  type    resnr   residue atom    cgnr    charge  mass
    1   opls_BZCG   1       BZCG    BCG1        1       0       78.113999
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement