After I run a script, I've got the following lines:

 PyMOL(TM) Molecular Graphics System, Version 1.4.1.
 Copyright (c) Schrodinger, LLC.
 All Rights Reserved.

    Created by Warren L. DeLano, Ph.D. 

    PyMOL is user-supported open-source software.  Although some versions
    are freely available, PyMOL is not in the public domain.

    If PyMOL is helpful in your work or study, then please volunteer 
    support for our ongoing efforts to create open and affordable scientific
    software by purchasing a PyMOL Maintenance and/or Support subscription.

    More information can be found at "http://www.pymol.org".

    Enter "help" for a list of commands.
    Enter "help <command-name>" for information on a specific command.

 Hit ESC anytime to toggle between text and graphics.

 Command mode. No graphics front end.
 Detected 8 CPU cores.  Enabled multithreaded rendering.
PyMOL>align MHC1, MHC2
 Match: read scoring matrix.
 Match: assigning 385 x 384 pairwise scores.
 MatchAlign: aligning residues (385 vs 384)...
 ExecutiveAlign: 3810 atoms aligned.
 Executive: RMS =    0.000 (3810 to 3810 atoms)
PyMOL>sele EP1, chain M
 Selector: selection "EP1" defined with 63 atoms.
PyMOL>sele EP2, chain R
 Selector: selection "EP2" defined with 64 atoms.
PyMOL>rms_cur EP1 and n. CA, EP2 and n. CA
 Executive: RMS =    7.457 (9 to 9 atoms)
 PyMOL: normal program termination.

I need to extract the value "7.457" from the line " Executive: RMS = 7.457 (9 to 9 atoms)". It should be noted that the "7.457" value, as well the "9 to 9 atoms" information will vary among different rounds, so I can't use it as a pattern. The "Executive: RMS" is not variable, but it is repeated some lines above. Apparently, I'll have the value always in the second last line. This could be used to extract the value, but I don't know how to do it with python or shell script.

Can someone help me? Thank you very much!

By the way, this is the script I'm working on(It's specific PyMol program, retrieving RMSD values):

## Importing PyMol files
from pymol.cgo import *
from pymol import cmd
from pymol import stored
# Loading MHC1
cmd.load ("MHC1.pdb")
#Change chain C to chain M (MHC1 epitope)
cmd.alter (('chain C'),'chain="M"')
# Loading MHC2
cmd.load ("MHC2.pdb")
#Change chain C to chain R (MHC2 epitope)
cmd.alter (('chain C'),'chain="R"')
## Align MHC1 and MHC2
cmd.do ("align MHC1, MHC2")
## MHC1 epitope selection (EP1)
cmd.do ("sele EP1, chain M")
## MHC2 epitope selection (EP2)
cmd.do ("sele EP2, chain R")
## Remove chain names (this is required so 'rms_cur' will work properly)
cmd.alter (("all"),'chain=""')
## Residues numbers aligned (this is required so 'rms_cur' will work properly)
cmd.alter (("all"),'segi=""')
## RMSD Calculation between EP1 and EP2
cmd.do ("rms_cur EP1 and n. CA, EP2 and n. CA")
  • It appears that this is an interactive program. Is that correct?
    – devnull
    Apr 15, 2014 at 13:59

2 Answers 2

script | sed -n '${x;p};h'

That should do it, I think. It will always print the second to last line.

If you want only the number you:

script | sed -n '${x;s/.*= *//;s/ .*//p};h'

So big H appends to sed's hold space the contents of the current pattern space, whereas little h overwrites it. So if you overwrite the hold space for every line, and on the $last line you exchange the hold space with the pattern space, then you're working with the second to last line.

This is the best possible solution to this problem that I can imagine because it uses the least amount of resources that could be necessary. You never have any more than two lines in memory at any time.

  • +1 but could you explain the cryptic sed please?
    – terdon
    Apr 15, 2014 at 14:22
  • @terdon - updated.
    – mikeserv
    Apr 15, 2014 at 14:57
  • @awk_FTW - updated.
    – mikeserv
    Apr 15, 2014 at 14:57
  • Cool, thanks. By the way, you only ever have one line in memory (and one variable) with the awk solutions below.
    – terdon
    Apr 15, 2014 at 15:10
  • @terdon - Maybe that's true, but sed is much faster than awk. davidlyness.com/post/…
    – mikeserv
    Apr 15, 2014 at 15:13

I am not entirely clear on how you get the output you show. I am assuming it is produced by the script you mentioned and that you can simply pipe it through something else to parse it. If so, these solutions should work:

your_script | tail -n 2 | awk '/RMS/{print $4}'

tail -n 2 prints the last two lines and the awk will print the 4th field of any line containing RMS, that is the value you are after.


your_script | tail -n 2 | grep -oP '[.\d]+' | head -1

That will grep for sets of numbers or . and uses head to print the first one.

Since you know you want the last line that contains RMS, you could also simply do:

your_script | awk '/: RMS/{val=$4}END{print val}' 

This will go through each line and every time it finds one that contains : RMS, it will save the 4th field as val. The END{} block is executed after all lines have been processed so at that point, val will be the last value found, the one you want.

  • @awk_FTW heh :) Same indeed.
    – terdon
    Apr 15, 2014 at 14:34

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.