madchemist
madchemist

Reputation: 164

Move a line matching a specific pattern to another line matching a different pattern using sed

I am a beginner in sed and awk, however I can do basic tasks. I have a problem with my work that involves rearranging certain lines in a file from one place to another.

In the following example, I would like to capture the line containing the patterns " O " (with whitespaces), and move it before the line containing pattern " N " so that:

    ATOM   1771  C   ALA A  61      48.797 
    ATOM   1772  O   ALA A  61      49.998 
    ATOM   1773  CB  ALA A  61      48.018 
    ATOM   1774  HB1 ALA A  61      48.964 
    ATOM   1775  HB2 ALA A  61      47.476 
    ATOM   1776  HB3 ALA A  61      47.420 
    ATOM   1777  N   LYS A  62      47.854 
    ATOM   1778  H   LYS A  62      46.979 
    ATOM   1779  CA  LYS A  62      48.163 
    ATOM   1780  HA  LYS A  62      49.236 
    ATOM   1781  C   LYS A  62      47.633 
    ATOM   1782  O   LYS A  62      47.789 
    ATOM   1783  CB  LYS A  62      47.541 
    ATOM   1784  HB2 LYS A  62      47.693 
    ATOM   1785  HB3 LYS A  62      46.473 
    ATOM   1798  HZ3 LYS A  62      45.853 
    ATOM   1799  N   GLY A  63      47.001 
    ATOM   1800  H   GLY A  63      46.906 

becomes:

    ATOM   1771  C   ALA A  61      48.797 
    ATOM   1773  CB  ALA A  61      48.018 
    ATOM   1774  HB1 ALA A  61      48.964 
    ATOM   1775  HB2 ALA A  61      47.476 
    ATOM   1776  HB3 ALA A  61      47.420 
    ATOM   1772  O   ALA A  61      49.998 
    ATOM   1777  N   LYS A  62      47.854 
    ATOM   1778  H   LYS A  62      46.979 
    ATOM   1779  CA  LYS A  62      48.163 
    ATOM   1780  HA  LYS A  62      49.236 
    ATOM   1781  C   LYS A  62      47.633 
    ATOM   1783  CB  LYS A  62      47.541 
    ATOM   1784  HB2 LYS A  62      47.693 
    ATOM   1785  HB3 LYS A  62      46.473 
    ATOM   1798  HZ3 LYS A  62      45.853 
    ATOM   1782  O   LYS A  62      47.789 
    ATOM   1799  N   GLY A  63      47.001 
    ATOM   1800  H   GLY A  63      46.906 

Any suggestions? Thanks a lot for your time!

Upvotes: 0

Views: 98

Answers (5)

potong
potong

Reputation: 58391

This might work for you (GNU sed):

sed '/\sO\s/{h;d};/\sN\s/{H;x}' file

Save the O line in the hold space and then delete it, append the N line to it and print out at the same time.

Upvotes: 1

Jotne
Jotne

Reputation: 41456

Another awk

awk '$3=="O" {f=$0;next} $3=="N" {$0=f RS$0}1'
    ATOM   1771  C   ALA A  61      48.797
    ATOM   1773  CB  ALA A  61      48.018
    ATOM   1774  HB1 ALA A  61      48.964
    ATOM   1775  HB2 ALA A  61      47.476
    ATOM   1776  HB3 ALA A  61      47.420
    ATOM   1772  O   ALA A  61      49.998
    ATOM   1777  N   LYS A  62      47.854
    ATOM   1778  H   LYS A  62      46.979
    ATOM   1779  CA  LYS A  62      48.163
    ATOM   1780  HA  LYS A  62      49.236
    ATOM   1781  C   LYS A  62      47.633
    ATOM   1783  CB  LYS A  62      47.541
    ATOM   1784  HB2 LYS A  62      47.693
    ATOM   1785  HB3 LYS A  62      46.473
    ATOM   1798  HZ3 LYS A  62      45.853
    ATOM   1782  O   LYS A  62      47.789
    ATOM   1799  N   GLY A  63      47.001
    ATOM   1800  H   GLY A  63      46.906

Upvotes: 1

Miller
Miller

Reputation: 35198

Using a perl one-liner

perl -ane '$F[2] eq "O" ? $o = $_ : print $F[2] eq "N" ? ($o, $_) : $_' file

Explanation:

Switches:

  • -a: Splits the line on space and loads them in an array @F
  • -n: Creates a while(<>){..} loop for each line in your input file.
  • -e: Tells perl to execute the code on command line.

Upvotes: 2

konsolebox
konsolebox

Reputation: 75478

This should work:

awk '$3 == "O" { T = $0; next; } $3 == "N" && T { print T; T = 0; } 1' your_file.txt

Exact output:

    ATOM   1771  C   ALA A  61      48.797 
    ATOM   1772  O   ALA A  61      49.998 
    ATOM   1773  CB  ALA A  61      48.018 
    ATOM   1774  HB1 ALA A  61      48.964 
    ATOM   1775  HB2 ALA A  61      47.476 
    ATOM   1776  HB3 ALA A  61      47.420 
    ATOM   1777  N   LYS A  62      47.854 
    ATOM   1778  H   LYS A  62      46.979 
    ATOM   1779  CA  LYS A  62      48.163 
    ATOM   1780  HA  LYS A  62      49.236 
    ATOM   1781  C   LYS A  62      47.633 
    ATOM   1782  O   LYS A  62      47.789 
    ATOM   1783  CB  LYS A  62      47.541 
    ATOM   1784  HB2 LYS A  62      47.693 
    ATOM   1785  HB3 LYS A  62      46.473 
    ATOM   1798  HZ3 LYS A  62      45.853 
    ATOM   1799  N   GLY A  63      47.001 
    ATOM   1800  H   GLY A  63      46.906 

Upvotes: 2

Avinash Raj
Avinash Raj

Reputation: 174706

This also shoul work,

$ awk -v RS="\0" -v FS='\n' '{for (i=1;i<=NF; i++) {if ($i~/\s*ATOM\s*[0-9]+\s*O.*/) {var=$i;} else if($i~/\s*ATOM\s*[0-9]+\s*N.*/) {print var"\n"$i} else print $i;}}' file
    ATOM   1771  C   ALA A  61      48.797 
    ATOM   1773  CB  ALA A  61      48.018 
    ATOM   1774  HB1 ALA A  61      48.964 
    ATOM   1775  HB2 ALA A  61      47.476 
    ATOM   1776  HB3 ALA A  61      47.420 
    ATOM   1772  O   ALA A  61      49.998 
    ATOM   1777  N   LYS A  62      47.854 
    ATOM   1778  H   LYS A  62      46.979 
    ATOM   1779  CA  LYS A  62      48.163 
    ATOM   1780  HA  LYS A  62      49.236 
    ATOM   1781  C   LYS A  62      47.633 
    ATOM   1783  CB  LYS A  62      47.541 
    ATOM   1784  HB2 LYS A  62      47.693 
    ATOM   1785  HB3 LYS A  62      46.473 
    ATOM   1798  HZ3 LYS A  62      45.853 
    ATOM   1782  O   LYS A  62      47.789 
    ATOM   1799  N   GLY A  63      47.001 
    ATOM   1800  H   GLY A  63      46.906 

Upvotes: 1

Related Questions